@promptbook/node 0.92.0-3 → 0.92.0-31

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 (172) hide show
  1. package/esm/index.es.js +796 -426
  2. package/esm/index.es.js.map +1 -1
  3. package/esm/typings/src/_packages/browser.index.d.ts +2 -0
  4. package/esm/typings/src/_packages/core.index.d.ts +22 -6
  5. package/esm/typings/src/_packages/deepseek.index.d.ts +2 -0
  6. package/esm/typings/src/_packages/google.index.d.ts +2 -0
  7. package/esm/typings/src/_packages/types.index.d.ts +4 -2
  8. package/esm/typings/src/_packages/utils.index.d.ts +2 -0
  9. package/esm/typings/src/cli/common/$provideLlmToolsForCli.d.ts +1 -1
  10. package/esm/typings/src/collection/PipelineCollection.d.ts +0 -2
  11. package/esm/typings/src/collection/SimplePipelineCollection.d.ts +1 -1
  12. package/esm/typings/src/commands/FOREACH/ForeachJson.d.ts +6 -6
  13. package/esm/typings/src/commands/FOREACH/foreachCommandParser.d.ts +0 -2
  14. package/esm/typings/src/commands/FORMFACTOR/formfactorCommandParser.d.ts +1 -1
  15. package/esm/typings/src/commands/_BOILERPLATE/boilerplateCommandParser.d.ts +1 -1
  16. package/esm/typings/src/commands/_common/types/CommandParser.d.ts +36 -28
  17. package/esm/typings/src/config.d.ts +41 -11
  18. package/esm/typings/src/constants.d.ts +43 -2
  19. package/esm/typings/src/conversion/archive/loadArchive.d.ts +2 -2
  20. package/esm/typings/src/errors/0-BoilerplateError.d.ts +2 -2
  21. package/esm/typings/src/executables/$provideExecutablesForNode.d.ts +1 -1
  22. package/esm/typings/src/executables/apps/locateLibreoffice.d.ts +2 -1
  23. package/esm/typings/src/executables/apps/locatePandoc.d.ts +2 -1
  24. package/esm/typings/src/executables/locateApp.d.ts +2 -2
  25. package/esm/typings/src/executables/platforms/locateAppOnLinux.d.ts +2 -1
  26. package/esm/typings/src/executables/platforms/locateAppOnMacOs.d.ts +2 -1
  27. package/esm/typings/src/executables/platforms/locateAppOnWindows.d.ts +2 -1
  28. package/esm/typings/src/execution/AbstractTaskResult.d.ts +1 -1
  29. package/esm/typings/src/execution/CommonToolsOptions.d.ts +5 -1
  30. package/esm/typings/src/execution/LlmExecutionToolsConstructor.d.ts +2 -1
  31. package/esm/typings/src/execution/PipelineExecutorResult.d.ts +4 -2
  32. package/esm/typings/src/execution/createPipelineExecutor/$OngoingTaskResult.d.ts +12 -9
  33. package/esm/typings/src/execution/createPipelineExecutor/10-executePipeline.d.ts +13 -10
  34. package/esm/typings/src/execution/createPipelineExecutor/20-executeTask.d.ts +12 -9
  35. package/esm/typings/src/execution/createPipelineExecutor/30-executeFormatSubvalues.d.ts +15 -3
  36. package/esm/typings/src/execution/createPipelineExecutor/40-executeAttempts.d.ts +20 -14
  37. package/esm/typings/src/execution/createPipelineExecutor/computeCosineSimilarity.d.ts +13 -0
  38. package/esm/typings/src/execution/createPipelineExecutor/filterJustOutputParameters.d.ts +7 -6
  39. package/esm/typings/src/execution/createPipelineExecutor/getContextForTask.d.ts +5 -1
  40. package/esm/typings/src/execution/createPipelineExecutor/getExamplesForTask.d.ts +1 -1
  41. package/esm/typings/src/execution/createPipelineExecutor/getKnowledgeForTask.d.ts +21 -5
  42. package/esm/typings/src/execution/createPipelineExecutor/getReservedParametersForTask.d.ts +19 -5
  43. package/esm/typings/src/execution/createPipelineExecutor/knowledgePiecesToString.d.ts +9 -0
  44. package/esm/typings/src/execution/translation/automatic-translate/automatic-translators/LindatAutomaticTranslator.d.ts +4 -4
  45. package/esm/typings/src/execution/utils/checkExpectations.d.ts +1 -1
  46. package/esm/typings/src/execution/utils/uncertainNumber.d.ts +3 -2
  47. package/esm/typings/src/formats/_common/{FormatDefinition.d.ts → FormatParser.d.ts} +8 -6
  48. package/esm/typings/src/formats/_common/FormatSubvalueParser.d.ts +66 -0
  49. package/esm/typings/src/formats/csv/CsvFormatParser.d.ts +17 -0
  50. package/esm/typings/src/formats/csv/CsvSettings.d.ts +2 -2
  51. package/esm/typings/src/formats/csv/utils/csvParse.d.ts +12 -0
  52. package/esm/typings/src/formats/csv/utils/isValidCsvString.d.ts +1 -1
  53. package/esm/typings/src/formats/index.d.ts +2 -2
  54. package/esm/typings/src/formats/json/{JsonFormatDefinition.d.ts → JsonFormatParser.d.ts} +6 -6
  55. package/esm/typings/src/formats/json/utils/isValidJsonString.d.ts +1 -1
  56. package/esm/typings/src/formats/json/utils/jsonParse.d.ts +8 -0
  57. package/esm/typings/src/formats/text/{TextFormatDefinition.d.ts → TextFormatParser.d.ts} +7 -7
  58. package/esm/typings/src/formats/xml/XmlFormatParser.d.ts +19 -0
  59. package/esm/typings/src/formats/xml/utils/isValidXmlString.d.ts +1 -1
  60. package/esm/typings/src/formfactors/_boilerplate/BoilerplateFormfactorDefinition.d.ts +3 -2
  61. package/esm/typings/src/formfactors/_common/AbstractFormfactorDefinition.d.ts +16 -7
  62. package/esm/typings/src/formfactors/_common/FormfactorDefinition.d.ts +3 -1
  63. package/esm/typings/src/formfactors/_common/string_formfactor_name.d.ts +2 -1
  64. package/esm/typings/src/formfactors/chatbot/ChatbotFormfactorDefinition.d.ts +2 -2
  65. package/esm/typings/src/formfactors/completion/CompletionFormfactorDefinition.d.ts +29 -0
  66. package/esm/typings/src/formfactors/generator/GeneratorFormfactorDefinition.d.ts +2 -1
  67. package/esm/typings/src/formfactors/generic/GenericFormfactorDefinition.d.ts +2 -2
  68. package/esm/typings/src/formfactors/index.d.ts +33 -8
  69. package/esm/typings/src/formfactors/matcher/MatcherFormfactorDefinition.d.ts +4 -2
  70. package/esm/typings/src/formfactors/sheets/SheetsFormfactorDefinition.d.ts +3 -2
  71. package/esm/typings/src/formfactors/translator/TranslatorFormfactorDefinition.d.ts +3 -2
  72. package/esm/typings/src/high-level-abstractions/index.d.ts +2 -2
  73. package/esm/typings/src/llm-providers/_common/register/$llmToolsMetadataRegister.d.ts +3 -3
  74. package/esm/typings/src/llm-providers/_common/register/$llmToolsRegister.d.ts +3 -3
  75. package/esm/typings/src/llm-providers/_common/register/$provideLlmToolsConfigurationFromEnv.d.ts +4 -4
  76. package/esm/typings/src/llm-providers/_common/register/$provideLlmToolsForTestingAndScriptsAndPlayground.d.ts +4 -3
  77. package/esm/typings/src/llm-providers/_common/register/$provideLlmToolsFromEnv.d.ts +17 -4
  78. package/esm/typings/src/llm-providers/_common/register/LlmToolsConfiguration.d.ts +11 -4
  79. package/esm/typings/src/llm-providers/_common/register/LlmToolsMetadata.d.ts +27 -5
  80. package/esm/typings/src/llm-providers/_common/register/LlmToolsOptions.d.ts +9 -2
  81. package/esm/typings/src/llm-providers/_common/register/createLlmToolsFromConfiguration.d.ts +12 -3
  82. package/esm/typings/src/llm-providers/_common/utils/cache/CacheItem.d.ts +10 -5
  83. package/esm/typings/src/llm-providers/_common/utils/cache/CacheLlmToolsOptions.d.ts +5 -3
  84. package/esm/typings/src/llm-providers/_common/utils/cache/cacheLlmTools.d.ts +3 -3
  85. package/esm/typings/src/llm-providers/_common/utils/count-total-usage/limitTotalUsage.d.ts +5 -5
  86. package/esm/typings/src/llm-providers/anthropic-claude/anthropic-claude-models.d.ts +1 -1
  87. package/esm/typings/src/llm-providers/azure-openai/AzureOpenAiExecutionTools.d.ts +4 -0
  88. package/esm/typings/src/llm-providers/deepseek/deepseek-models.d.ts +23 -0
  89. package/esm/typings/src/llm-providers/google/google-models.d.ts +23 -0
  90. package/esm/typings/src/llm-providers/openai/OpenAiExecutionTools.d.ts +4 -0
  91. package/esm/typings/src/llm-providers/openai/openai-models.d.ts +1 -1
  92. package/esm/typings/src/llm-providers/openai/register-configuration.d.ts +2 -2
  93. package/esm/typings/src/llm-providers/openai/register-constructor.d.ts +2 -2
  94. package/esm/typings/src/migrations/migratePipeline.d.ts +9 -0
  95. package/esm/typings/src/other/templates/getBookTemplates.d.ts +2 -2
  96. package/esm/typings/src/personas/preparePersona.d.ts +1 -1
  97. package/esm/typings/src/pipeline/PipelineInterface/PipelineInterface.d.ts +3 -3
  98. package/esm/typings/src/pipeline/PipelineInterface/constants.d.ts +1 -1
  99. package/esm/typings/src/pipeline/PipelineInterface/getPipelineInterface.d.ts +1 -1
  100. package/esm/typings/src/pipeline/PipelineInterface/isPipelineImplementingInterface.d.ts +5 -4
  101. package/esm/typings/src/pipeline/PipelineInterface/isPipelineInterfacesEqual.d.ts +1 -1
  102. package/esm/typings/src/pipeline/PipelineJson/CommonTaskJson.d.ts +9 -6
  103. package/esm/typings/src/pipeline/PipelineJson/PersonaJson.d.ts +4 -2
  104. package/esm/typings/src/pipeline/PipelineJson/PipelineJson.d.ts +3 -2
  105. package/esm/typings/src/pipeline/PipelineString.d.ts +3 -1
  106. package/esm/typings/src/pipeline/book-notation.d.ts +2 -2
  107. package/esm/typings/src/postprocessing/utils/extractJsonBlock.d.ts +1 -1
  108. package/esm/typings/src/prepare/prepareTasks.d.ts +7 -4
  109. package/esm/typings/src/remote-server/openapi-types.d.ts +348 -6
  110. package/esm/typings/src/remote-server/openapi.d.ts +398 -4
  111. package/esm/typings/src/remote-server/types/RemoteServerOptions.d.ts +2 -1
  112. package/esm/typings/src/scrapers/_boilerplate/BoilerplateScraper.d.ts +3 -3
  113. package/esm/typings/src/scrapers/_boilerplate/createBoilerplateScraper.d.ts +1 -1
  114. package/esm/typings/src/scrapers/_boilerplate/register-metadata.d.ts +1 -1
  115. package/esm/typings/src/scrapers/_common/Converter.d.ts +3 -1
  116. package/esm/typings/src/scrapers/_common/Scraper.d.ts +4 -3
  117. package/esm/typings/src/scrapers/_common/ScraperIntermediateSource.d.ts +4 -2
  118. package/esm/typings/src/scrapers/_common/register/$provideFilesystemForNode.d.ts +2 -1
  119. package/esm/typings/src/scrapers/_common/register/$provideScrapersForBrowser.d.ts +6 -3
  120. package/esm/typings/src/scrapers/_common/register/$provideScrapersForNode.d.ts +3 -5
  121. package/esm/typings/src/scrapers/_common/register/$scrapersMetadataRegister.d.ts +3 -3
  122. package/esm/typings/src/scrapers/_common/register/$scrapersRegister.d.ts +3 -2
  123. package/esm/typings/src/scrapers/_common/register/ScraperAndConverterMetadata.d.ts +8 -5
  124. package/esm/typings/src/scrapers/_common/register/ScraperConstructor.d.ts +2 -1
  125. package/esm/typings/src/scrapers/_common/utils/getScraperIntermediateSource.d.ts +6 -5
  126. package/esm/typings/src/scrapers/_common/utils/makeKnowledgeSourceHandler.d.ts +3 -1
  127. package/esm/typings/src/scrapers/document/createDocumentScraper.d.ts +1 -1
  128. package/esm/typings/src/scrapers/document-legacy/createLegacyDocumentScraper.d.ts +2 -1
  129. package/esm/typings/src/scrapers/markdown/createMarkdownScraper.d.ts +4 -1
  130. package/esm/typings/src/scrapers/markitdown/MarkitdownScraper.d.ts +1 -1
  131. package/esm/typings/src/scrapers/pdf/createPdfScraper.d.ts +2 -1
  132. package/esm/typings/src/scrapers/website/createWebsiteScraper.d.ts +3 -4
  133. package/esm/typings/src/scripting/javascript/postprocessing-functions.d.ts +5 -1
  134. package/esm/typings/src/storage/file-cache-storage/FileCacheStorage.d.ts +12 -5
  135. package/esm/typings/src/storage/file-cache-storage/FileCacheStorageOptions.d.ts +4 -2
  136. package/esm/typings/src/storage/file-cache-storage/utils/nameToSubfolderPath.d.ts +2 -1
  137. package/esm/typings/src/storage/local-storage/getIndexedDbStorage.d.ts +10 -0
  138. package/esm/typings/src/storage/local-storage/utils/makePromptbookStorageFromIndexedDb.d.ts +7 -0
  139. package/esm/typings/src/storage/local-storage/utils/makePromptbookStorageFromWebStorage.d.ts +2 -1
  140. package/esm/typings/src/types/IntermediateFilesStrategy.d.ts +2 -1
  141. package/esm/typings/src/types/ModelVariant.d.ts +5 -5
  142. package/esm/typings/src/types/typeAliases.d.ts +17 -13
  143. package/esm/typings/src/utils/$Register.d.ts +8 -7
  144. package/esm/typings/src/utils/editable/edit-pipeline-string/addPipelineCommand.d.ts +2 -2
  145. package/esm/typings/src/utils/editable/edit-pipeline-string/deflatePipeline.d.ts +4 -1
  146. package/esm/typings/src/utils/editable/utils/isFlatPipeline.d.ts +2 -1
  147. package/esm/typings/src/utils/environment/$getGlobalScope.d.ts +2 -1
  148. package/esm/typings/src/utils/expectation-counters/index.d.ts +1 -1
  149. package/esm/typings/src/utils/markdown/extractAllListItemsFromMarkdown.d.ts +1 -1
  150. package/esm/typings/src/utils/normalization/nameToUriPart.d.ts +4 -4
  151. package/esm/typings/src/utils/normalization/nameToUriParts.d.ts +4 -4
  152. package/esm/typings/src/utils/normalization/normalize-to-kebab-case.d.ts +3 -3
  153. package/esm/typings/src/utils/normalization/normalizeTo_SCREAMING_CASE.d.ts +3 -3
  154. package/esm/typings/src/utils/normalization/normalizeTo_camelCase.d.ts +4 -4
  155. package/esm/typings/src/utils/normalization/normalizeTo_snake_case.d.ts +3 -3
  156. package/esm/typings/src/utils/normalization/removeDiacritics.d.ts +3 -3
  157. package/esm/typings/src/utils/normalization/searchKeywords.d.ts +4 -1
  158. package/esm/typings/src/utils/normalization/titleToName.d.ts +4 -4
  159. package/esm/typings/src/utils/organization/empty_object.d.ts +2 -2
  160. package/esm/typings/src/utils/organization/just_empty_object.d.ts +4 -4
  161. package/esm/typings/src/utils/parameters/mapAvailableToExpectedParameters.d.ts +7 -7
  162. package/esm/typings/src/utils/serialization/clonePipeline.d.ts +4 -3
  163. package/esm/typings/src/utils/serialization/deepClone.d.ts +5 -1
  164. package/esm/typings/src/utils/validators/javascriptName/isValidJavascriptName.d.ts +3 -3
  165. package/esm/typings/src/utils/validators/parameterName/validateParameterName.d.ts +5 -4
  166. package/esm/typings/src/version.d.ts +2 -1
  167. package/package.json +2 -2
  168. package/umd/index.umd.js +799 -429
  169. package/umd/index.umd.js.map +1 -1
  170. package/esm/typings/src/formats/_common/FormatSubvalueDefinition.d.ts +0 -31
  171. package/esm/typings/src/formats/csv/CsvFormatDefinition.d.ts +0 -17
  172. package/esm/typings/src/formats/xml/XmlFormatDefinition.d.ts +0 -19
package/esm/index.es.js CHANGED
@@ -5,8 +5,8 @@ import spaceTrim, { spaceTrim as spaceTrim$1 } from 'spacetrim';
5
5
  import JSZip from 'jszip';
6
6
  import { format } from 'prettier';
7
7
  import parserHtml from 'prettier/parser-html';
8
- import { Subject } from 'rxjs';
9
8
  import { randomBytes } from 'crypto';
9
+ import { Subject } from 'rxjs';
10
10
  import { forTime } from 'waitasecond';
11
11
  import { parse, unparse } from 'papaparse';
12
12
  import hexEncoder from 'crypto-js/enc-hex';
@@ -30,7 +30,7 @@ const BOOK_LANGUAGE_VERSION = '1.0.0';
30
30
  * @generated
31
31
  * @see https://github.com/webgptorg/promptbook
32
32
  */
33
- const PROMPTBOOK_ENGINE_VERSION = '0.92.0-3';
33
+ const PROMPTBOOK_ENGINE_VERSION = '0.92.0-31';
34
34
  /**
35
35
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
36
36
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -101,6 +101,21 @@ const DEFAULT_BOOK_OUTPUT_PARAMETER_NAME = 'result';
101
101
  * @public exported from `@promptbook/core`
102
102
  */
103
103
  const DEFAULT_MAX_FILE_SIZE = 100 * 1024 * 1024; // 100MB
104
+ /**
105
+ * Threshold value that determines when a dataset is considered "big"
106
+ * and may require special handling or optimizations
107
+ *
108
+ * For example, when error occurs in one item of the big dataset, it will not fail the whole pipeline
109
+ *
110
+ * @public exported from `@promptbook/core`
111
+ */
112
+ const BIG_DATASET_TRESHOLD = 50;
113
+ /**
114
+ * Placeholder text used to represent a placeholder value of failed operation
115
+ *
116
+ * @public exported from `@promptbook/core`
117
+ */
118
+ const FAILED_VALUE_PLACEHOLDER = '!?';
104
119
  // <- TODO: [🧠] Better system for generator warnings - not always "code" and "by `@promptbook/cli`"
105
120
  /**
106
121
  * The maximum number of iterations for a loops
@@ -195,7 +210,7 @@ ex-port const WIZZARD_APP_ID: string_app_id = 'wizzard';
195
210
  const DEFAULT_PIPELINE_COLLECTION_BASE_FILENAME = `index`;
196
211
  // <- TODO: [🧜‍♂️]
197
212
  /**
198
- * @@@
213
+ * Default settings for parsing and generating CSV files in Promptbook.
199
214
  *
200
215
  * @public exported from `@promptbook/core`
201
216
  */
@@ -206,19 +221,19 @@ const DEFAULT_CSV_SETTINGS = Object.freeze({
206
221
  skipEmptyLines: true,
207
222
  });
208
223
  /**
209
- * @@@
224
+ * Controls whether verbose logging is enabled by default throughout the application.
210
225
  *
211
226
  * @public exported from `@promptbook/core`
212
227
  */
213
228
  let DEFAULT_IS_VERBOSE = false;
214
229
  /**
215
- * @@@
230
+ * Controls whether auto-installation of dependencies is enabled by default.
216
231
  *
217
232
  * @public exported from `@promptbook/core`
218
233
  */
219
234
  const DEFAULT_IS_AUTO_INSTALLED = false;
220
235
  /**
221
- * @@@
236
+ * Indicates whether pipeline logic validation is enabled. When true, the pipeline logic is checked for consistency.
222
237
  *
223
238
  * @private within the repository
224
239
  */
@@ -299,6 +314,42 @@ class UnexpectedError extends Error {
299
314
  }
300
315
  }
301
316
 
317
+ /**
318
+ * Converts a JavaScript Object Notation (JSON) string into an object.
319
+ *
320
+ * Note: This is wrapper around `JSON.parse()` with better error and type handling
321
+ *
322
+ * @public exported from `@promptbook/utils`
323
+ */
324
+ function jsonParse(value) {
325
+ if (value === undefined) {
326
+ throw new Error(`Can not parse JSON from undefined value.`);
327
+ }
328
+ else if (typeof value !== 'string') {
329
+ console.error('Can not parse JSON from non-string value.', { text: value });
330
+ throw new Error(spaceTrim(`
331
+ Can not parse JSON from non-string value.
332
+
333
+ The value type: ${typeof value}
334
+ See more in console.
335
+ `));
336
+ }
337
+ try {
338
+ return JSON.parse(value);
339
+ }
340
+ catch (error) {
341
+ if (!(error instanceof Error)) {
342
+ throw error;
343
+ }
344
+ throw new Error(spaceTrim((block) => `
345
+ ${block(error.message)}
346
+
347
+ The JSON text:
348
+ ${block(value)}
349
+ `));
350
+ }
351
+ }
352
+
302
353
  /**
303
354
  * Orders JSON object by keys
304
355
  *
@@ -528,8 +579,12 @@ function checkSerializableAsJson(options) {
528
579
  */
529
580
 
530
581
  /**
531
- * @@@
582
+ * Creates a deep clone of the given object
583
+ *
584
+ * Note: This method only works for objects that are fully serializable to JSON and do not contain functions, Dates, or special types.
532
585
  *
586
+ * @param objectValue The object to clone.
587
+ * @returns A deep, writable clone of the input object.
533
588
  * @public exported from `@promptbook/utils`
534
589
  */
535
590
  function deepClone(objectValue) {
@@ -611,13 +666,13 @@ const ORDER_OF_PIPELINE_JSON = [
611
666
  */
612
667
  const REPLACING_NONCE = 'ptbkauk42kV2dzao34faw7FudQUHYPtW';
613
668
  /**
614
- * @@@
669
+ * Placeholder value indicating a parameter is missing its value.
615
670
  *
616
671
  * @private within the repository
617
672
  */
618
673
  const RESERVED_PARAMETER_MISSING_VALUE = 'MISSING-' + REPLACING_NONCE;
619
674
  /**
620
- * @@@
675
+ * Placeholder value indicating a parameter is restricted and cannot be used directly.
621
676
  *
622
677
  * @private within the repository
623
678
  */
@@ -1088,7 +1143,7 @@ async function loadArchive(filePath, fs) {
1088
1143
  if (!indexFile) {
1089
1144
  throw new UnexpectedError(`Archive does not contain 'index.book.json' file`);
1090
1145
  }
1091
- const collectionJson = JSON.parse(await indexFile.async('text'));
1146
+ const collectionJson = jsonParse(await indexFile.async('text'));
1092
1147
  for (const pipeline of collectionJson) {
1093
1148
  validatePipeline(pipeline);
1094
1149
  }
@@ -1098,7 +1153,7 @@ async function loadArchive(filePath, fs) {
1098
1153
  * Note: [🟢] Code in this file should never be never released in packages that could be imported into browser environment
1099
1154
  */
1100
1155
 
1101
- 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:"availableModelNames",description:"List of available model names separated by comma (,)",isInput:true,isOutput:false},{name:"personaDescription",description:"Description of the persona",isInput:true,isOutput:false},{name:"modelRequirements",description:"Specific requirements for the model",isInput:false,isOutput:true}],tasks:[{taskType:"PROMPT_TASK",name:"make-model-requirements",title:"Make modelRequirements",content:"You are experienced AI engineer, you need to create virtual assistant.\nWrite\n\n## Example\n\n```json\n{\n\"modelName\": \"gpt-4o\",\n\"systemMessage\": \"You are experienced AI engineer and helpfull assistant.\",\n\"temperature\": 0.7\n}\n```\n\n## Instructions\n\n- Your output format is JSON object\n- Write just the JSON object, no other text should be present\n- It contains the following keys:\n - `modelName`: The name of the model to use\n - `systemMessage`: The system message to provide context to the model\n - `temperature`: The sampling temperature to use\n\n### Key `modelName`\n\nPick from the following models:\n\n- {availableModelNames}\n\n### Key `systemMessage`\n\nThe system message is used to communicate instructions or provide context to the model at the beginning of a conversation. It is displayed in a different format compared to user messages, helping the model understand its role in the conversation. The system message typically guides the model's behavior, sets the tone, or specifies desired output from the model. By utilizing the system message effectively, users can steer the model towards generating more accurate and relevant responses.\n\nFor example:\n\n> You are an experienced AI engineer and helpful assistant.\n\n> You are a friendly and knowledgeable chatbot.\n\n### Key `temperature`\n\nThe sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, the model will use log probability to automatically increase the temperature until certain thresholds are hit.\n\nYou can pick a value between 0 and 2. For example:\n\n- `0.1`: Low temperature, extremely conservative and deterministic\n- `0.5`: Medium temperature, balanced between conservative and creative\n- `1.0`: High temperature, creative and bit random\n- `1.5`: Very high temperature, extremely creative and often chaotic and unpredictable\n- `2.0`: Maximum temperature, completely random and unpredictable, for some extreme creative use cases\n\n# The assistant\n\nTake this description of the persona:\n\n> {personaDescription}",resultingParameterName:"modelRequirements",format:"JSON",dependentParameterNames:["availableModelNames","personaDescription"]}],personas:[],preparations:[],knowledgeSources:[],knowledgePieces:[],sources:[{type:"BOOK",path:null,content:"# Prepare Persona\n\n- PIPELINE URL `https://promptbook.studio/promptbook/prepare-persona.book`\n- INPUT PARAMETER `{availableModelNames}` List of available model names separated by comma (,)\n- INPUT PARAMETER `{personaDescription}` Description of the persona\n- OUTPUT PARAMETER `{modelRequirements}` Specific requirements for the model\n\n## Make modelRequirements\n\n- FORMAT JSON\n\n```markdown\nYou are experienced AI engineer, you need to create virtual assistant.\nWrite\n\n## Example\n\n\\`\\`\\`json\n{\n\"modelName\": \"gpt-4o\",\n\"systemMessage\": \"You are experienced AI engineer and helpfull assistant.\",\n\"temperature\": 0.7\n}\n\\`\\`\\`\n\n## Instructions\n\n- Your output format is JSON object\n- Write just the JSON object, no other text should be present\n- It contains the following keys:\n - `modelName`: The name of the model to use\n - `systemMessage`: The system message to provide context to the model\n - `temperature`: The sampling temperature to use\n\n### Key `modelName`\n\nPick from the following models:\n\n- {availableModelNames}\n\n### Key `systemMessage`\n\nThe system message is used to communicate instructions or provide context to the model at the beginning of a conversation. It is displayed in a different format compared to user messages, helping the model understand its role in the conversation. The system message typically guides the model's behavior, sets the tone, or specifies desired output from the model. By utilizing the system message effectively, users can steer the model towards generating more accurate and relevant responses.\n\nFor example:\n\n> You are an experienced AI engineer and helpful assistant.\n\n> You are a friendly and knowledgeable chatbot.\n\n### Key `temperature`\n\nThe sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, the model will use log probability to automatically increase the temperature until certain thresholds are hit.\n\nYou can pick a value between 0 and 2. For example:\n\n- `0.1`: Low temperature, extremely conservative and deterministic\n- `0.5`: Medium temperature, balanced between conservative and creative\n- `1.0`: High temperature, creative and bit random\n- `1.5`: Very high temperature, extremely creative and often chaotic and unpredictable\n- `2.0`: Maximum temperature, completely random and unpredictable, for some extreme creative use cases\n\n# The assistant\n\nTake this description of the persona:\n\n> {personaDescription}\n```\n\n`-> {modelRequirements}`\n"}],sourceFile:"./books/prepare-persona.book"},{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"}];
1156
+ 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"}];
1102
1157
 
1103
1158
  /**
1104
1159
  * Checks if value is valid email
@@ -1168,7 +1223,7 @@ function isValidFilePath(filename) {
1168
1223
  * Function isValidJsonString will tell you if the string is valid JSON or not
1169
1224
  *
1170
1225
  * @param value The string to check
1171
- * @returns True if the string is a valid JSON string, false otherwise
1226
+ * @returns `true` if the string is a valid JSON string, false otherwise
1172
1227
  *
1173
1228
  * @public exported from `@promptbook/utils`
1174
1229
  */
@@ -1449,7 +1504,7 @@ function extractParameterNames(template) {
1449
1504
  */
1450
1505
  function unpreparePipeline(pipeline) {
1451
1506
  let { personas, knowledgeSources, tasks } = pipeline;
1452
- personas = personas.map((persona) => ({ ...persona, modelRequirements: undefined, preparationIds: undefined }));
1507
+ personas = personas.map((persona) => ({ ...persona, modelsRequirements: undefined, preparationIds: undefined }));
1453
1508
  knowledgeSources = knowledgeSources.map((knowledgeSource) => ({ ...knowledgeSource, preparationIds: undefined }));
1454
1509
  tasks = tasks.map((task) => {
1455
1510
  let { dependentParameterNames } = task;
@@ -1490,7 +1545,7 @@ class SimplePipelineCollection {
1490
1545
  /**
1491
1546
  * Constructs a pipeline collection from pipelines
1492
1547
  *
1493
- * @param pipelines @@@
1548
+ * @param pipelines Array of pipeline JSON objects to include in the collection
1494
1549
  *
1495
1550
  * Note: During the construction logic of all pipelines are validated
1496
1551
  * Note: It is not recommended to use this constructor directly, use `createCollectionFromJson` *(or other variant)* instead
@@ -1620,15 +1675,21 @@ class MissingToolsError extends Error {
1620
1675
  * @public exported from `@promptbook/core`
1621
1676
  */
1622
1677
  function isPipelinePrepared(pipeline) {
1623
- // Note: Ignoring `pipeline.preparations` @@@
1624
- // Note: Ignoring `pipeline.knowledgePieces` @@@
1678
+ // Note: Ignoring `pipeline.preparations`
1679
+ // Note: Ignoring `pipeline.knowledgePieces`
1625
1680
  if (pipeline.title === undefined || pipeline.title === '' || pipeline.title === DEFAULT_BOOK_TITLE) {
1681
+ // TODO: !!! Comment this out
1682
+ console.log('Pipeline is not prepared because title is undefined or empty', pipeline);
1626
1683
  return false;
1627
1684
  }
1628
- if (!pipeline.personas.every((persona) => persona.modelRequirements !== undefined)) {
1685
+ if (!pipeline.personas.every((persona) => persona.modelsRequirements !== undefined)) {
1686
+ // TODO: !!! Comment this out
1687
+ console.log('Pipeline is not prepared because personas are not prepared', pipeline.personas);
1629
1688
  return false;
1630
1689
  }
1631
1690
  if (!pipeline.knowledgeSources.every((knowledgeSource) => knowledgeSource.preparationIds !== undefined)) {
1691
+ // TODO: !!! Comment this out
1692
+ console.log('Pipeline is not prepared because knowledge sources are not prepared', pipeline.knowledgeSources);
1632
1693
  return false;
1633
1694
  }
1634
1695
  /*
@@ -1649,70 +1710,6 @@ function isPipelinePrepared(pipeline) {
1649
1710
  * - [♨] Are tasks prepared
1650
1711
  */
1651
1712
 
1652
- /**
1653
- * Generates random token
1654
- *
1655
- * Note: This function is cryptographically secure (it uses crypto.randomBytes internally)
1656
- *
1657
- * @private internal helper function
1658
- * @returns secure random token
1659
- */
1660
- function $randomToken(randomness) {
1661
- return randomBytes(randomness).toString('hex');
1662
- }
1663
- /**
1664
- * TODO: Maybe use nanoid instead https://github.com/ai/nanoid
1665
- */
1666
-
1667
- /**
1668
- * Recursively converts JSON strings to JSON objects
1669
-
1670
- * @public exported from `@promptbook/utils`
1671
- */
1672
- function jsonStringsToJsons(object) {
1673
- if (object === null) {
1674
- return object;
1675
- }
1676
- if (Array.isArray(object)) {
1677
- return object.map(jsonStringsToJsons);
1678
- }
1679
- if (typeof object !== 'object') {
1680
- return object;
1681
- }
1682
- const newObject = { ...object };
1683
- for (const [key, value] of Object.entries(object)) {
1684
- if (typeof value === 'string' && isValidJsonString(value)) {
1685
- newObject[key] = JSON.parse(value);
1686
- }
1687
- else {
1688
- newObject[key] = jsonStringsToJsons(value);
1689
- }
1690
- }
1691
- return newObject;
1692
- }
1693
- /**
1694
- * TODO: Type the return type correctly
1695
- */
1696
-
1697
- /**
1698
- * This error indicates errors during the execution of the pipeline
1699
- *
1700
- * @public exported from `@promptbook/core`
1701
- */
1702
- class PipelineExecutionError extends Error {
1703
- constructor(message) {
1704
- // Added id parameter
1705
- super(message);
1706
- this.name = 'PipelineExecutionError';
1707
- // TODO: [🐙] DRY - Maybe $randomId
1708
- this.id = `error-${$randomToken(8 /* <- TODO: To global config + Use Base58 to avoid simmilar char conflicts */)}`;
1709
- Object.setPrototypeOf(this, PipelineExecutionError.prototype);
1710
- }
1711
- }
1712
- /**
1713
- * TODO: [🧠][🌂] Add id to all errors
1714
- */
1715
-
1716
1713
  /**
1717
1714
  * This error indicates problems parsing the format value
1718
1715
  *
@@ -1847,6 +1844,40 @@ class NotYetImplementedError extends Error {
1847
1844
  }
1848
1845
  }
1849
1846
 
1847
+ /**
1848
+ * Generates random token
1849
+ *
1850
+ * Note: This function is cryptographically secure (it uses crypto.randomBytes internally)
1851
+ *
1852
+ * @private internal helper function
1853
+ * @returns secure random token
1854
+ */
1855
+ function $randomToken(randomness) {
1856
+ return randomBytes(randomness).toString('hex');
1857
+ }
1858
+ /**
1859
+ * TODO: Maybe use nanoid instead https://github.com/ai/nanoid
1860
+ */
1861
+
1862
+ /**
1863
+ * This error indicates errors during the execution of the pipeline
1864
+ *
1865
+ * @public exported from `@promptbook/core`
1866
+ */
1867
+ class PipelineExecutionError extends Error {
1868
+ constructor(message) {
1869
+ // Added id parameter
1870
+ super(message);
1871
+ this.name = 'PipelineExecutionError';
1872
+ // TODO: [🐙] DRY - Maybe $randomId
1873
+ this.id = `error-${$randomToken(8 /* <- TODO: To global config + Use Base58 to avoid simmilar char conflicts */)}`;
1874
+ Object.setPrototypeOf(this, PipelineExecutionError.prototype);
1875
+ }
1876
+ }
1877
+ /**
1878
+ * TODO: [🧠][🌂] Add id to all errors
1879
+ */
1880
+
1850
1881
  /**
1851
1882
  * Error thrown when a fetch request fails
1852
1883
  *
@@ -1922,6 +1953,65 @@ const ALL_ERRORS = {
1922
1953
  * Note: [💞] Ignore a discrepancy between file name and entity name
1923
1954
  */
1924
1955
 
1956
+ /**
1957
+ * Serializes an error into a [🚉] JSON-serializable object
1958
+ *
1959
+ * @public exported from `@promptbook/utils`
1960
+ */
1961
+ function serializeError(error) {
1962
+ const { name, message, stack } = error;
1963
+ const { id } = error;
1964
+ if (!Object.keys(ALL_ERRORS).includes(name)) {
1965
+ console.error(spaceTrim((block) => `
1966
+
1967
+ Cannot serialize error with name "${name}"
1968
+
1969
+ Authors of Promptbook probably forgot to add this error into the list of errors:
1970
+ https://github.com/webgptorg/promptbook/blob/main/src/errors/0-index.ts
1971
+
1972
+
1973
+ ${block(stack || message)}
1974
+
1975
+ `));
1976
+ }
1977
+ return {
1978
+ name: name,
1979
+ message,
1980
+ stack,
1981
+ id, // Include id in the serialized object
1982
+ };
1983
+ }
1984
+
1985
+ /**
1986
+ * Recursively converts JSON strings to JSON objects
1987
+
1988
+ * @public exported from `@promptbook/utils`
1989
+ */
1990
+ function jsonStringsToJsons(object) {
1991
+ if (object === null) {
1992
+ return object;
1993
+ }
1994
+ if (Array.isArray(object)) {
1995
+ return object.map(jsonStringsToJsons);
1996
+ }
1997
+ if (typeof object !== 'object') {
1998
+ return object;
1999
+ }
2000
+ const newObject = { ...object };
2001
+ for (const [key, value] of Object.entries(object)) {
2002
+ if (typeof value === 'string' && isValidJsonString(value)) {
2003
+ newObject[key] = jsonParse(value);
2004
+ }
2005
+ else {
2006
+ newObject[key] = jsonStringsToJsons(value);
2007
+ }
2008
+ }
2009
+ return newObject;
2010
+ }
2011
+ /**
2012
+ * TODO: Type the return type correctly
2013
+ */
2014
+
1925
2015
  /**
1926
2016
  * Deserializes the error object
1927
2017
  *
@@ -2088,33 +2178,72 @@ function createTask(options) {
2088
2178
  */
2089
2179
 
2090
2180
  /**
2091
- * Serializes an error into a [🚉] JSON-serializable object
2181
+ * Represents the uncertain value
2092
2182
  *
2093
- * @public exported from `@promptbook/utils`
2183
+ * @public exported from `@promptbook/core`
2184
+ */
2185
+ const ZERO_VALUE = $deepFreeze({ value: 0 });
2186
+ /**
2187
+ * Represents the uncertain value
2188
+ *
2189
+ * @public exported from `@promptbook/core`
2190
+ */
2191
+ const UNCERTAIN_ZERO_VALUE = $deepFreeze({ value: 0, isUncertain: true });
2192
+ /**
2193
+ * Represents the usage with no resources consumed
2194
+ *
2195
+ * @public exported from `@promptbook/core`
2196
+ */
2197
+ const ZERO_USAGE = $deepFreeze({
2198
+ price: ZERO_VALUE,
2199
+ input: {
2200
+ tokensCount: ZERO_VALUE,
2201
+ charactersCount: ZERO_VALUE,
2202
+ wordsCount: ZERO_VALUE,
2203
+ sentencesCount: ZERO_VALUE,
2204
+ linesCount: ZERO_VALUE,
2205
+ paragraphsCount: ZERO_VALUE,
2206
+ pagesCount: ZERO_VALUE,
2207
+ },
2208
+ output: {
2209
+ tokensCount: ZERO_VALUE,
2210
+ charactersCount: ZERO_VALUE,
2211
+ wordsCount: ZERO_VALUE,
2212
+ sentencesCount: ZERO_VALUE,
2213
+ linesCount: ZERO_VALUE,
2214
+ paragraphsCount: ZERO_VALUE,
2215
+ pagesCount: ZERO_VALUE,
2216
+ },
2217
+ });
2218
+ /**
2219
+ * Represents the usage with unknown resources consumed
2220
+ *
2221
+ * @public exported from `@promptbook/core`
2222
+ */
2223
+ const UNCERTAIN_USAGE = $deepFreeze({
2224
+ price: UNCERTAIN_ZERO_VALUE,
2225
+ input: {
2226
+ tokensCount: UNCERTAIN_ZERO_VALUE,
2227
+ charactersCount: UNCERTAIN_ZERO_VALUE,
2228
+ wordsCount: UNCERTAIN_ZERO_VALUE,
2229
+ sentencesCount: UNCERTAIN_ZERO_VALUE,
2230
+ linesCount: UNCERTAIN_ZERO_VALUE,
2231
+ paragraphsCount: UNCERTAIN_ZERO_VALUE,
2232
+ pagesCount: UNCERTAIN_ZERO_VALUE,
2233
+ },
2234
+ output: {
2235
+ tokensCount: UNCERTAIN_ZERO_VALUE,
2236
+ charactersCount: UNCERTAIN_ZERO_VALUE,
2237
+ wordsCount: UNCERTAIN_ZERO_VALUE,
2238
+ sentencesCount: UNCERTAIN_ZERO_VALUE,
2239
+ linesCount: UNCERTAIN_ZERO_VALUE,
2240
+ paragraphsCount: UNCERTAIN_ZERO_VALUE,
2241
+ pagesCount: UNCERTAIN_ZERO_VALUE,
2242
+ },
2243
+ });
2244
+ /**
2245
+ * Note: [💞] Ignore a discrepancy between file name and entity name
2094
2246
  */
2095
- function serializeError(error) {
2096
- const { name, message, stack } = error;
2097
- const { id } = error;
2098
- if (!Object.keys(ALL_ERRORS).includes(name)) {
2099
- console.error(spaceTrim((block) => `
2100
-
2101
- Cannot serialize error with name "${name}"
2102
-
2103
- Authors of Promptbook probably forgot to add this error into the list of errors:
2104
- https://github.com/webgptorg/promptbook/blob/main/src/errors/0-index.ts
2105
-
2106
-
2107
- ${block(stack || message)}
2108
-
2109
- `));
2110
- }
2111
- return {
2112
- name: name,
2113
- message,
2114
- stack,
2115
- id, // Include id in the serialized object
2116
- };
2117
- }
2118
2247
 
2119
2248
  /**
2120
2249
  * Format either small or big number
@@ -2197,74 +2326,6 @@ function valueToString(value) {
2197
2326
  }
2198
2327
  }
2199
2328
 
2200
- /**
2201
- * Represents the uncertain value
2202
- *
2203
- * @public exported from `@promptbook/core`
2204
- */
2205
- const ZERO_VALUE = $deepFreeze({ value: 0 });
2206
- /**
2207
- * Represents the uncertain value
2208
- *
2209
- * @public exported from `@promptbook/core`
2210
- */
2211
- const UNCERTAIN_ZERO_VALUE = $deepFreeze({ value: 0, isUncertain: true });
2212
- /**
2213
- * Represents the usage with no resources consumed
2214
- *
2215
- * @public exported from `@promptbook/core`
2216
- */
2217
- const ZERO_USAGE = $deepFreeze({
2218
- price: ZERO_VALUE,
2219
- input: {
2220
- tokensCount: ZERO_VALUE,
2221
- charactersCount: ZERO_VALUE,
2222
- wordsCount: ZERO_VALUE,
2223
- sentencesCount: ZERO_VALUE,
2224
- linesCount: ZERO_VALUE,
2225
- paragraphsCount: ZERO_VALUE,
2226
- pagesCount: ZERO_VALUE,
2227
- },
2228
- output: {
2229
- tokensCount: ZERO_VALUE,
2230
- charactersCount: ZERO_VALUE,
2231
- wordsCount: ZERO_VALUE,
2232
- sentencesCount: ZERO_VALUE,
2233
- linesCount: ZERO_VALUE,
2234
- paragraphsCount: ZERO_VALUE,
2235
- pagesCount: ZERO_VALUE,
2236
- },
2237
- });
2238
- /**
2239
- * Represents the usage with unknown resources consumed
2240
- *
2241
- * @public exported from `@promptbook/core`
2242
- */
2243
- $deepFreeze({
2244
- price: UNCERTAIN_ZERO_VALUE,
2245
- input: {
2246
- tokensCount: UNCERTAIN_ZERO_VALUE,
2247
- charactersCount: UNCERTAIN_ZERO_VALUE,
2248
- wordsCount: UNCERTAIN_ZERO_VALUE,
2249
- sentencesCount: UNCERTAIN_ZERO_VALUE,
2250
- linesCount: UNCERTAIN_ZERO_VALUE,
2251
- paragraphsCount: UNCERTAIN_ZERO_VALUE,
2252
- pagesCount: UNCERTAIN_ZERO_VALUE,
2253
- },
2254
- output: {
2255
- tokensCount: UNCERTAIN_ZERO_VALUE,
2256
- charactersCount: UNCERTAIN_ZERO_VALUE,
2257
- wordsCount: UNCERTAIN_ZERO_VALUE,
2258
- sentencesCount: UNCERTAIN_ZERO_VALUE,
2259
- linesCount: UNCERTAIN_ZERO_VALUE,
2260
- paragraphsCount: UNCERTAIN_ZERO_VALUE,
2261
- pagesCount: UNCERTAIN_ZERO_VALUE,
2262
- },
2263
- });
2264
- /**
2265
- * Note: [💞] Ignore a discrepancy between file name and entity name
2266
- */
2267
-
2268
2329
  /**
2269
2330
  * Function `addUsage` will add multiple usages into one
2270
2331
  *
@@ -2473,7 +2534,7 @@ function union(...sets) {
2473
2534
  }
2474
2535
 
2475
2536
  /**
2476
- * @@@
2537
+ * Contains configuration options for parsing and generating CSV files, such as delimiters and quoting rules.
2477
2538
  *
2478
2539
  * @public exported from `@promptbook/core`
2479
2540
  */
@@ -2482,11 +2543,29 @@ const MANDATORY_CSV_SETTINGS = Object.freeze({
2482
2543
  // encoding: 'utf-8',
2483
2544
  });
2484
2545
 
2546
+ /**
2547
+ * Converts a CSV string into an object
2548
+ *
2549
+ * Note: This is wrapper around `papaparse.parse()` with better autohealing
2550
+ *
2551
+ * @private - for now until `@promptbook/csv` is released
2552
+ */
2553
+ function csvParse(value /* <- TODO: string_csv */, settings, schema /* <- TODO: Make CSV Schemas */) {
2554
+ settings = { ...settings, ...MANDATORY_CSV_SETTINGS };
2555
+ // Note: Autoheal invalid '\n' characters
2556
+ if (settings.newline && !settings.newline.includes('\r') && value.includes('\r')) {
2557
+ console.warn('CSV string contains carriage return characters, but in the CSV settings the `newline` setting does not include them. Autohealing the CSV string.');
2558
+ value = value.replace(/\r\n/g, '\n').replace(/\r/g, '\n');
2559
+ }
2560
+ const csv = parse(value, settings);
2561
+ return csv;
2562
+ }
2563
+
2485
2564
  /**
2486
2565
  * Function to check if a string is valid CSV
2487
2566
  *
2488
2567
  * @param value The string to check
2489
- * @returns True if the string is a valid CSV string, false otherwise
2568
+ * @returns `true` if the string is a valid CSV string, false otherwise
2490
2569
  *
2491
2570
  * @public exported from `@promptbook/utils`
2492
2571
  */
@@ -2510,7 +2589,7 @@ function isValidCsvString(value) {
2510
2589
  * @public exported from `@promptbook/core`
2511
2590
  * <- TODO: [🏢] Export from package `@promptbook/csv`
2512
2591
  */
2513
- const CsvFormatDefinition = {
2592
+ const CsvFormatParser = {
2514
2593
  formatName: 'CSV',
2515
2594
  aliases: ['SPREADSHEET', 'TABLE'],
2516
2595
  isValid(value, settings, schema) {
@@ -2522,12 +2601,12 @@ const CsvFormatDefinition = {
2522
2601
  heal(value, settings, schema) {
2523
2602
  throw new Error('Not implemented');
2524
2603
  },
2525
- subvalueDefinitions: [
2604
+ subvalueParsers: [
2526
2605
  {
2527
2606
  subvalueName: 'ROW',
2528
- async mapValues(value, outputParameterName, settings, mapCallback) {
2529
- // TODO: [👨🏾‍🤝‍👨🏼] DRY csv parsing
2530
- const csv = parse(value, { ...settings, ...MANDATORY_CSV_SETTINGS });
2607
+ async mapValues(options) {
2608
+ const { value, outputParameterName, settings, mapCallback, onProgress } = options;
2609
+ const csv = csvParse(value, settings);
2531
2610
  if (csv.errors.length !== 0) {
2532
2611
  throw new CsvFormatError(spaceTrim((block) => `
2533
2612
  CSV parsing error
@@ -2542,23 +2621,37 @@ const CsvFormatDefinition = {
2542
2621
  ${block(value)}
2543
2622
  `));
2544
2623
  }
2545
- const mappedData = await Promise.all(csv.data.map(async (row, index) => {
2624
+ const mappedData = [];
2625
+ const length = csv.data.length;
2626
+ for (let index = 0; index < length; index++) {
2627
+ const row = csv.data[index];
2546
2628
  if (row[outputParameterName]) {
2547
2629
  throw new CsvFormatError(`Can not overwrite existing column "${outputParameterName}" in CSV row`);
2548
2630
  }
2549
- return {
2631
+ const mappedRow = {
2550
2632
  ...row,
2551
- [outputParameterName]: await mapCallback(row, index),
2633
+ [outputParameterName]: await mapCallback(row, index, length),
2552
2634
  };
2553
- }));
2635
+ mappedData.push(mappedRow);
2636
+ if (onProgress) {
2637
+ // Note: Report the CSV with all rows mapped so far
2638
+ /*
2639
+ // TODO: [🛕] Report progress with all the rows including the pending ones
2640
+ const progressData = mappedData.map((row, i) =>
2641
+ i > index ? { ...row, [outputParameterName]: PENDING_VALUE_PLACEHOLDER } : row,
2642
+ );
2643
+ */
2644
+ await onProgress(unparse(mappedData, { ...settings, ...MANDATORY_CSV_SETTINGS }));
2645
+ }
2646
+ }
2554
2647
  return unparse(mappedData, { ...settings, ...MANDATORY_CSV_SETTINGS });
2555
2648
  },
2556
2649
  },
2557
2650
  {
2558
2651
  subvalueName: 'CELL',
2559
- async mapValues(value, outputParameterName, settings, mapCallback) {
2560
- // TODO: [👨🏾‍🤝‍👨🏼] DRY csv parsing
2561
- const csv = parse(value, { ...settings, ...MANDATORY_CSV_SETTINGS });
2652
+ async mapValues(options) {
2653
+ const { value, settings, mapCallback, onProgress } = options;
2654
+ const csv = csvParse(value, settings);
2562
2655
  if (csv.errors.length !== 0) {
2563
2656
  throw new CsvFormatError(spaceTrim((block) => `
2564
2657
  CSV parsing error
@@ -2574,9 +2667,9 @@ const CsvFormatDefinition = {
2574
2667
  `));
2575
2668
  }
2576
2669
  const mappedData = await Promise.all(csv.data.map(async (row, rowIndex) => {
2577
- return /* not await */ Promise.all(Object.entries(row).map(async ([key, value], columnIndex) => {
2670
+ return /* not await */ Promise.all(Object.entries(row).map(async ([key, value], columnIndex, array) => {
2578
2671
  const index = rowIndex * Object.keys(row).length + columnIndex;
2579
- return /* not await */ mapCallback({ [key]: value }, index);
2672
+ return /* not await */ mapCallback({ [key]: value }, index, array.length);
2580
2673
  }));
2581
2674
  }));
2582
2675
  return unparse(mappedData, { ...settings, ...MANDATORY_CSV_SETTINGS });
@@ -2585,10 +2678,10 @@ const CsvFormatDefinition = {
2585
2678
  ],
2586
2679
  };
2587
2680
  /**
2588
- * TODO: [🍓] In `CsvFormatDefinition` implement simple `isValid`
2589
- * TODO: [🍓] In `CsvFormatDefinition` implement partial `canBeValid`
2590
- * TODO: [🍓] In `CsvFormatDefinition` implement `heal
2591
- * TODO: [🍓] In `CsvFormatDefinition` implement `subvalueDefinitions`
2681
+ * TODO: [🍓] In `CsvFormatParser` implement simple `isValid`
2682
+ * TODO: [🍓] In `CsvFormatParser` implement partial `canBeValid`
2683
+ * TODO: [🍓] In `CsvFormatParser` implement `heal
2684
+ * TODO: [🍓] In `CsvFormatParser` implement `subvalueParsers`
2592
2685
  * TODO: [🏢] Allow to expect something inside CSV objects and other formats
2593
2686
  */
2594
2687
 
@@ -2597,7 +2690,7 @@ const CsvFormatDefinition = {
2597
2690
  *
2598
2691
  * @private still in development [🏢]
2599
2692
  */
2600
- const JsonFormatDefinition = {
2693
+ const JsonFormatParser = {
2601
2694
  formatName: 'JSON',
2602
2695
  mimeType: 'application/json',
2603
2696
  isValid(value, settings, schema) {
@@ -2609,28 +2702,28 @@ const JsonFormatDefinition = {
2609
2702
  heal(value, settings, schema) {
2610
2703
  throw new Error('Not implemented');
2611
2704
  },
2612
- subvalueDefinitions: [],
2705
+ subvalueParsers: [],
2613
2706
  };
2614
2707
  /**
2615
2708
  * TODO: [🧠] Maybe propper instance of object
2616
2709
  * TODO: [0] Make string_serialized_json
2617
2710
  * TODO: [1] Make type for JSON Settings and Schema
2618
2711
  * TODO: [🧠] What to use for validating JSONs - JSON Schema, ZoD, typescript types/interfaces,...?
2619
- * TODO: [🍓] In `JsonFormatDefinition` implement simple `isValid`
2620
- * TODO: [🍓] In `JsonFormatDefinition` implement partial `canBeValid`
2621
- * TODO: [🍓] In `JsonFormatDefinition` implement `heal
2622
- * TODO: [🍓] In `JsonFormatDefinition` implement `subvalueDefinitions`
2712
+ * TODO: [🍓] In `JsonFormatParser` implement simple `isValid`
2713
+ * TODO: [🍓] In `JsonFormatParser` implement partial `canBeValid`
2714
+ * TODO: [🍓] In `JsonFormatParser` implement `heal
2715
+ * TODO: [🍓] In `JsonFormatParser` implement `subvalueParsers`
2623
2716
  * TODO: [🏢] Allow to expect something inside JSON objects and other formats
2624
2717
  */
2625
2718
 
2626
2719
  /**
2627
2720
  * Definition for any text - this will be always valid
2628
2721
  *
2629
- * Note: This is not useful for validation, but for splitting and mapping with `subvalueDefinitions`
2722
+ * Note: This is not useful for validation, but for splitting and mapping with `subvalueParsers`
2630
2723
  *
2631
2724
  * @public exported from `@promptbook/core`
2632
2725
  */
2633
- const TextFormatDefinition = {
2726
+ const TextFormatParser = {
2634
2727
  formatName: 'TEXT',
2635
2728
  isValid(value) {
2636
2729
  return typeof value === 'string';
@@ -2639,19 +2732,20 @@ const TextFormatDefinition = {
2639
2732
  return typeof partialValue === 'string';
2640
2733
  },
2641
2734
  heal() {
2642
- throw new UnexpectedError('It does not make sense to call `TextFormatDefinition.heal`');
2735
+ throw new UnexpectedError('It does not make sense to call `TextFormatParser.heal`');
2643
2736
  },
2644
- subvalueDefinitions: [
2737
+ subvalueParsers: [
2645
2738
  {
2646
2739
  subvalueName: 'LINE',
2647
- async mapValues(value, outputParameterName, settings, mapCallback) {
2740
+ async mapValues(options) {
2741
+ const { value, mapCallback, onProgress } = options;
2648
2742
  const lines = value.split('\n');
2649
- const mappedLines = await Promise.all(lines.map((lineContent, lineNumber) =>
2743
+ const mappedLines = await Promise.all(lines.map((lineContent, lineNumber, array) =>
2650
2744
  // TODO: [🧠] Maybe option to skip empty line
2651
2745
  /* not await */ mapCallback({
2652
2746
  lineContent,
2653
2747
  // TODO: [🧠] Maybe also put here `lineNumber`
2654
- }, lineNumber)));
2748
+ }, lineNumber, array.length)));
2655
2749
  return mappedLines.join('\n');
2656
2750
  },
2657
2751
  },
@@ -2661,10 +2755,10 @@ const TextFormatDefinition = {
2661
2755
  /**
2662
2756
  * TODO: [1] Make type for XML Text and Schema
2663
2757
  * TODO: [🧠][🤠] Here should be all words, characters, lines, paragraphs, pages available as subvalues
2664
- * TODO: [🍓] In `TextFormatDefinition` implement simple `isValid`
2665
- * TODO: [🍓] In `TextFormatDefinition` implement partial `canBeValid`
2666
- * TODO: [🍓] In `TextFormatDefinition` implement `heal
2667
- * TODO: [🍓] In `TextFormatDefinition` implement `subvalueDefinitions`
2758
+ * TODO: [🍓] In `TextFormatParser` implement simple `isValid`
2759
+ * TODO: [🍓] In `TextFormatParser` implement partial `canBeValid`
2760
+ * TODO: [🍓] In `TextFormatParser` implement `heal
2761
+ * TODO: [🍓] In `TextFormatParser` implement `subvalueParsers`
2668
2762
  * TODO: [🏢] Allow to expect something inside each item of list and other formats
2669
2763
  */
2670
2764
 
@@ -2672,7 +2766,7 @@ const TextFormatDefinition = {
2672
2766
  * Function to check if a string is valid XML
2673
2767
  *
2674
2768
  * @param value
2675
- * @returns True if the string is a valid XML string, false otherwise
2769
+ * @returns `true` if the string is a valid XML string, false otherwise
2676
2770
  *
2677
2771
  * @public exported from `@promptbook/utils`
2678
2772
  */
@@ -2697,7 +2791,7 @@ function isValidXmlString(value) {
2697
2791
  *
2698
2792
  * @private still in development [🏢]
2699
2793
  */
2700
- const XmlFormatDefinition = {
2794
+ const XmlFormatParser = {
2701
2795
  formatName: 'XML',
2702
2796
  mimeType: 'application/xml',
2703
2797
  isValid(value, settings, schema) {
@@ -2709,17 +2803,17 @@ const XmlFormatDefinition = {
2709
2803
  heal(value, settings, schema) {
2710
2804
  throw new Error('Not implemented');
2711
2805
  },
2712
- subvalueDefinitions: [],
2806
+ subvalueParsers: [],
2713
2807
  };
2714
2808
  /**
2715
2809
  * TODO: [🧠] Maybe propper instance of object
2716
2810
  * TODO: [0] Make string_serialized_xml
2717
2811
  * TODO: [1] Make type for XML Settings and Schema
2718
2812
  * TODO: [🧠] What to use for validating XMLs - XSD,...
2719
- * TODO: [🍓] In `XmlFormatDefinition` implement simple `isValid`
2720
- * TODO: [🍓] In `XmlFormatDefinition` implement partial `canBeValid`
2721
- * TODO: [🍓] In `XmlFormatDefinition` implement `heal
2722
- * TODO: [🍓] In `XmlFormatDefinition` implement `subvalueDefinitions`
2813
+ * TODO: [🍓] In `XmlFormatParser` implement simple `isValid`
2814
+ * TODO: [🍓] In `XmlFormatParser` implement partial `canBeValid`
2815
+ * TODO: [🍓] In `XmlFormatParser` implement `heal
2816
+ * TODO: [🍓] In `XmlFormatParser` implement `subvalueParsers`
2723
2817
  * TODO: [🏢] Allow to expect something inside XML and other formats
2724
2818
  */
2725
2819
 
@@ -2728,24 +2822,19 @@ const XmlFormatDefinition = {
2728
2822
  *
2729
2823
  * @private internal index of `...` <- TODO [🏢]
2730
2824
  */
2731
- const FORMAT_DEFINITIONS = [
2732
- JsonFormatDefinition,
2733
- XmlFormatDefinition,
2734
- TextFormatDefinition,
2735
- CsvFormatDefinition,
2736
- ];
2825
+ const FORMAT_DEFINITIONS = [JsonFormatParser, XmlFormatParser, TextFormatParser, CsvFormatParser];
2737
2826
  /**
2738
2827
  * Note: [💞] Ignore a discrepancy between file name and entity name
2739
2828
  */
2740
2829
 
2741
2830
  /**
2742
- * Maps available parameters to expected parameters
2831
+ * Maps available parameters to expected parameters for a pipeline task.
2743
2832
  *
2744
2833
  * The strategy is:
2745
- * 1) @@@
2746
- * 2) @@@
2834
+ * 1) First, match parameters by name where both available and expected.
2835
+ * 2) Then, if there are unmatched expected and available parameters, map them by order.
2747
2836
  *
2748
- * @throws {PipelineExecutionError} @@@
2837
+ * @throws {PipelineExecutionError} If the number of unmatched expected and available parameters does not match, or mapping is ambiguous.
2749
2838
  * @private within the repository used in `createPipelineExecutor`
2750
2839
  */
2751
2840
  function mapAvailableToExpectedParameters(options) {
@@ -2768,7 +2857,7 @@ function mapAvailableToExpectedParameters(options) {
2768
2857
  else if (!availableParametersNames.has(parameterName) && expectedParameterNames.has(parameterName)) ;
2769
2858
  }
2770
2859
  if (expectedParameterNames.size === 0) {
2771
- // Note: [👨‍👨‍👧] Now we can freeze `mappedParameters` to prevent @@@
2860
+ // Note: [👨‍👨‍👧] Now we can freeze `mappedParameters` to prevent accidental modifications after mapping
2772
2861
  Object.freeze(mappedParameters);
2773
2862
  return mappedParameters;
2774
2863
  }
@@ -2799,7 +2888,7 @@ function mapAvailableToExpectedParameters(options) {
2799
2888
  for (let i = 0; i < expectedParameterNames.size; i++) {
2800
2889
  mappedParameters[expectedParameterNamesArray[i]] = availableParameters[availableParametersNamesArray[i]];
2801
2890
  }
2802
- // Note: [👨‍👨‍👧] Now we can freeze `mappedParameters` to prevent @@@
2891
+ // Note: [👨‍👨‍👧] Now we can freeze `mappedParameters` to prevent accidental modifications after mapping
2803
2892
  Object.freeze(mappedParameters);
2804
2893
  return mappedParameters;
2805
2894
  }
@@ -3095,7 +3184,7 @@ function extractJsonBlock(markdown) {
3095
3184
  }
3096
3185
  /**
3097
3186
  * TODO: Add some auto-healing logic + extract YAML, JSON5, TOML, etc.
3098
- * TODO: [🏢] Make this logic part of `JsonFormatDefinition` or `isValidJsonString`
3187
+ * TODO: [🏢] Make this logic part of `JsonFormatParser` or `isValidJsonString`
3099
3188
  */
3100
3189
 
3101
3190
  /**
@@ -3174,10 +3263,12 @@ function templateParameters(template, parameters) {
3174
3263
  throw new PipelineExecutionError('Parameter is already opened or not closed');
3175
3264
  }
3176
3265
  if (parameters[parameterName] === undefined) {
3266
+ console.log('!!! templateParameters 1', { parameterName, template, parameters });
3177
3267
  throw new PipelineExecutionError(`Parameter \`{${parameterName}}\` is not defined`);
3178
3268
  }
3179
3269
  let parameterValue = parameters[parameterName];
3180
3270
  if (parameterValue === undefined) {
3271
+ console.log('!!! templateParameters 2', { parameterName, template, parameters });
3181
3272
  throw new PipelineExecutionError(`Parameter \`{${parameterName}}\` is not defined`);
3182
3273
  }
3183
3274
  parameterValue = valueToString(parameterValue);
@@ -3548,10 +3639,10 @@ for (let i = 0; i < defaultDiacriticsRemovalMap.length; i++) {
3548
3639
  */
3549
3640
 
3550
3641
  /**
3551
- * @@@
3642
+ * Removes diacritic marks (accents) from characters in a string.
3552
3643
  *
3553
- * @param input @@@
3554
- * @returns @@@
3644
+ * @param input The string containing diacritics to be normalized.
3645
+ * @returns The string with diacritics removed or normalized.
3555
3646
  * @public exported from `@promptbook/utils`
3556
3647
  */
3557
3648
  function removeDiacritics(input) {
@@ -3594,7 +3685,7 @@ const CountUtils = {
3594
3685
  PAGES: countPages,
3595
3686
  };
3596
3687
  /**
3597
- * TODO: [🧠][🤠] This should be probbably as part of `TextFormatDefinition`
3688
+ * TODO: [🧠][🤠] This should be probbably as part of `TextFormatParser`
3598
3689
  * Note: [💞] Ignore a discrepancy between file name and entity name
3599
3690
  */
3600
3691
 
@@ -3622,13 +3713,17 @@ function checkExpectations(expectations, value) {
3622
3713
  }
3623
3714
  /**
3624
3715
  * TODO: [💝] Unite object for expecting amount and format
3625
- * TODO: [🧠][🤠] This should be part of `TextFormatDefinition`
3716
+ * TODO: [🧠][🤠] This should be part of `TextFormatParser`
3626
3717
  * Note: [💝] and [🤠] are interconnected together
3627
3718
  */
3628
3719
 
3629
3720
  /**
3630
- * @@@
3721
+ * Executes a pipeline task with multiple attempts, including joker and retry logic. Handles different task types
3722
+ * (prompt, script, dialog, etc.), applies postprocessing, checks expectations, and updates the execution report.
3723
+ * Throws errors if execution fails after all attempts.
3631
3724
  *
3725
+ * @param options - The options for execution, including task, parameters, pipeline, and configuration.
3726
+ * @returns The result string of the executed task.
3632
3727
  * @private internal utility of `createPipelineExecutor`
3633
3728
  */
3634
3729
  async function executeAttempts(options) {
@@ -3850,7 +3945,7 @@ async function executeAttempts(options) {
3850
3945
  if (task.format) {
3851
3946
  if (task.format === 'JSON') {
3852
3947
  if (!isValidJsonString($ongoingTaskResult.$resultString || '')) {
3853
- // TODO: [🏢] Do more universally via `FormatDefinition`
3948
+ // TODO: [🏢] Do more universally via `FormatParser`
3854
3949
  try {
3855
3950
  $ongoingTaskResult.$resultString = extractJsonBlock($ongoingTaskResult.$resultString || '');
3856
3951
  }
@@ -3952,12 +4047,16 @@ async function executeAttempts(options) {
3952
4047
  */
3953
4048
 
3954
4049
  /**
3955
- * @@@
4050
+ * Executes a pipeline task that requires mapping or iterating over subvalues of a parameter (such as rows in a CSV).
4051
+ * Handles format and subformat resolution, error handling, and progress reporting.
4052
+ *
4053
+ * @param options - Options for execution, including task details and progress callback.
4054
+ * @returns The result of the subvalue mapping or execution attempts.
3956
4055
  *
3957
4056
  * @private internal utility of `createPipelineExecutor`
3958
4057
  */
3959
4058
  async function executeFormatSubvalues(options) {
3960
- const { task, jokerParameterNames, parameters, priority, csvSettings, pipelineIdentification } = options;
4059
+ const { task, jokerParameterNames, parameters, priority, csvSettings, onProgress, pipelineIdentification } = options;
3961
4060
  if (task.foreach === undefined) {
3962
4061
  return /* not await */ executeAttempts(options);
3963
4062
  }
@@ -3988,16 +4087,16 @@ async function executeFormatSubvalues(options) {
3988
4087
  ${block(pipelineIdentification)}
3989
4088
  `));
3990
4089
  }
3991
- const subvalueDefinition = formatDefinition.subvalueDefinitions.find((subvalueDefinition) => [subvalueDefinition.subvalueName, ...(subvalueDefinition.aliases || [])].includes(task.foreach.subformatName));
3992
- if (subvalueDefinition === undefined) {
4090
+ const subvalueParser = formatDefinition.subvalueParsers.find((subvalueParser) => [subvalueParser.subvalueName, ...(subvalueParser.aliases || [])].includes(task.foreach.subformatName));
4091
+ if (subvalueParser === undefined) {
3993
4092
  throw new UnexpectedError(
3994
4093
  // <- TODO: [🧠][🧐] Should be formats fixed per promptbook version or behave as plugins (=> change UnexpectedError)
3995
4094
  spaceTrim((block) => `
3996
4095
  Unsupported subformat name "${task.foreach.subformatName}" for format "${task.foreach.formatName}"
3997
4096
 
3998
4097
  Available subformat names for format "${formatDefinition.formatName}":
3999
- ${block(formatDefinition.subvalueDefinitions
4000
- .map((subvalueDefinition) => subvalueDefinition.subvalueName)
4098
+ ${block(formatDefinition.subvalueParsers
4099
+ .map((subvalueParser) => subvalueParser.subvalueName)
4001
4100
  .map((subvalueName) => `- ${subvalueName}`)
4002
4101
  .join('\n'))}
4003
4102
 
@@ -4011,53 +4110,83 @@ async function executeFormatSubvalues(options) {
4011
4110
  formatSettings = csvSettings;
4012
4111
  // <- TODO: [🤹‍♂️] More universal, make simmilar pattern for other formats for example \n vs \r\n in text
4013
4112
  }
4014
- const resultString = await subvalueDefinition.mapValues(parameterValue, task.foreach.outputSubparameterName, formatSettings, async (subparameters, index) => {
4015
- let mappedParameters;
4016
- // TODO: [🤹‍♂️][🪂] Limit to N concurrent executions
4017
- // TODO: When done [🐚] Report progress also for each subvalue here
4018
- try {
4019
- mappedParameters = mapAvailableToExpectedParameters({
4020
- expectedParameters: Object.fromEntries(task.foreach.inputSubparameterNames.map((subparameterName) => [subparameterName, null])),
4021
- availableParameters: subparameters,
4022
- });
4023
- }
4024
- catch (error) {
4025
- if (!(error instanceof PipelineExecutionError)) {
4026
- throw error;
4113
+ const resultString = await subvalueParser.mapValues({
4114
+ value: parameterValue,
4115
+ outputParameterName: task.foreach.outputSubparameterName,
4116
+ settings: formatSettings,
4117
+ onProgress(partialResultString) {
4118
+ return onProgress(Object.freeze({
4119
+ [task.resultingParameterName]: partialResultString,
4120
+ }));
4121
+ },
4122
+ async mapCallback(subparameters, index, length) {
4123
+ let mappedParameters;
4124
+ try {
4125
+ mappedParameters = mapAvailableToExpectedParameters({
4126
+ expectedParameters: Object.fromEntries(task.foreach.inputSubparameterNames.map((subparameterName) => [subparameterName, null])),
4127
+ availableParameters: subparameters,
4128
+ });
4027
4129
  }
4028
- throw new PipelineExecutionError(spaceTrim((block) => `
4029
- ${error.message}
4130
+ catch (error) {
4131
+ if (!(error instanceof PipelineExecutionError)) {
4132
+ throw error;
4133
+ }
4134
+ const highLevelError = new PipelineExecutionError(spaceTrim((block) => `
4135
+ ${error.message}
4030
4136
 
4031
- This is error in FOREACH command
4032
- You have probbably passed wrong data to pipeline or wrong data was generated which are processed by FOREACH command
4137
+ This is error in FOREACH command when mapping ${formatDefinition.formatName} ${subvalueParser.subvalueName} data (${index + 1}/${length})
4138
+ You have probbably passed wrong data to pipeline or wrong data was generated which are processed by FOREACH command
4033
4139
 
4034
- ${block(pipelineIdentification)}
4035
- Subparameter index: ${index}
4036
- `));
4037
- }
4038
- const allSubparameters = {
4039
- ...parameters,
4040
- ...mappedParameters,
4041
- };
4042
- // 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
4043
- Object.freeze(allSubparameters);
4044
- const subresultString = await executeAttempts({
4045
- ...options,
4046
- priority: priority + index,
4047
- parameters: allSubparameters,
4048
- pipelineIdentification: spaceTrim((block) => `
4049
- ${block(pipelineIdentification)}
4050
- Subparameter index: ${index}
4051
- `),
4052
- });
4053
- return subresultString;
4140
+ ${block(pipelineIdentification)}
4141
+ `));
4142
+ if (length > BIG_DATASET_TRESHOLD) {
4143
+ console.error(highLevelError);
4144
+ return FAILED_VALUE_PLACEHOLDER;
4145
+ }
4146
+ throw highLevelError;
4147
+ }
4148
+ const allSubparameters = {
4149
+ ...parameters,
4150
+ ...mappedParameters,
4151
+ };
4152
+ Object.freeze(allSubparameters);
4153
+ try {
4154
+ const subresultString = await executeAttempts({
4155
+ ...options,
4156
+ priority: priority + index,
4157
+ parameters: allSubparameters,
4158
+ pipelineIdentification: spaceTrim((block) => `
4159
+ ${block(pipelineIdentification)}
4160
+ Subparameter index: ${index}
4161
+ `),
4162
+ });
4163
+ return subresultString;
4164
+ }
4165
+ catch (error) {
4166
+ if (length > BIG_DATASET_TRESHOLD) {
4167
+ console.error(spaceTrim((block) => `
4168
+ ${error.message}
4169
+
4170
+ This is error in FOREACH command when processing ${formatDefinition.formatName} ${subvalueParser.subvalueName} data (${index + 1}/${length})
4171
+
4172
+ ${block(pipelineIdentification)}
4173
+ `));
4174
+ return FAILED_VALUE_PLACEHOLDER;
4175
+ }
4176
+ throw error;
4177
+ }
4178
+ },
4054
4179
  });
4055
4180
  return resultString;
4056
4181
  }
4057
4182
 
4058
4183
  /**
4059
- * @@@
4184
+ * Returns the context for a given task, typically used to provide additional information or variables
4185
+ * required for the execution of the task within a pipeline. The context is returned as a string value
4186
+ * that may include markdown formatting.
4060
4187
  *
4188
+ * @param task - The task for which the context is being generated. This should be a deeply immutable TaskJson object.
4189
+ * @returns The context as a string, formatted as markdown and parameter value.
4061
4190
  * @private internal utility of `createPipelineExecutor`
4062
4191
  */
4063
4192
  async function getContextForTask(task) {
@@ -4065,7 +4194,7 @@ async function getContextForTask(task) {
4065
4194
  }
4066
4195
 
4067
4196
  /**
4068
- * @@@
4197
+ * Retrieves example values or templates for a given task, used to guide or validate pipeline execution.
4069
4198
  *
4070
4199
  * @private internal utility of `createPipelineExecutor`
4071
4200
  */
@@ -4074,25 +4203,127 @@ async function getExamplesForTask(task) {
4074
4203
  }
4075
4204
 
4076
4205
  /**
4077
- * @@@
4206
+ * Computes the cosine similarity between two embedding vectors
4207
+ *
4208
+ * Note: This is helping function for RAG (retrieval-augmented generation)
4209
+ *
4210
+ * @param embeddingVector1
4211
+ * @param embeddingVector2
4212
+ * @returns Cosine similarity between the two vectors
4213
+ *
4214
+ * @public exported from `@promptbook/core`
4215
+ */
4216
+ function computeCosineSimilarity(embeddingVector1, embeddingVector2) {
4217
+ if (embeddingVector1.length !== embeddingVector2.length) {
4218
+ throw new TypeError('Embedding vectors must have the same length');
4219
+ }
4220
+ const dotProduct = embeddingVector1.reduce((sum, value, index) => sum + value * embeddingVector2[index], 0);
4221
+ const magnitude1 = Math.sqrt(embeddingVector1.reduce((sum, value) => sum + value * value, 0));
4222
+ const magnitude2 = Math.sqrt(embeddingVector2.reduce((sum, value) => sum + value * value, 0));
4223
+ return 1 - dotProduct / (magnitude1 * magnitude2);
4224
+ }
4225
+
4226
+ /**
4227
+ *
4228
+ * @param knowledgePieces
4229
+ * @returns
4230
+ *
4231
+ * @private internal utility of `createPipelineExecutor`
4232
+ */
4233
+ function knowledgePiecesToString(knowledgePieces) {
4234
+ return knowledgePieces
4235
+ .map((knowledgePiece) => {
4236
+ const { content } = knowledgePiece;
4237
+ return `- ${content}`;
4238
+ })
4239
+ .join('\n');
4240
+ // <- TODO: [🧠] Some smarter aggregation of knowledge pieces, single-line vs multi-line vs mixed
4241
+ }
4242
+
4243
+ /**
4244
+ * Retrieves the most relevant knowledge pieces for a given task using embedding-based similarity search.
4245
+ * This is where retrieval-augmented generation (RAG) is performed to enhance the task with external knowledge.
4078
4246
  *
4079
4247
  * @private internal utility of `createPipelineExecutor`
4080
4248
  */
4081
4249
  async function getKnowledgeForTask(options) {
4082
- const { preparedPipeline, task } = options;
4083
- return preparedPipeline.knowledgePieces.map(({ content }) => `- ${content}`).join('\n');
4084
- // <- TODO: [🧠] Some smart aggregation of knowledge pieces, single-line vs multi-line vs mixed
4250
+ const { tools, preparedPipeline, task, parameters } = options;
4251
+ const firstKnowlegePiece = preparedPipeline.knowledgePieces[0];
4252
+ const firstKnowlegeIndex = firstKnowlegePiece === null || firstKnowlegePiece === void 0 ? void 0 : firstKnowlegePiece.index[0];
4253
+ // <- TODO: Do not use just first knowledge piece and first index to determine embedding model, use also keyword search
4254
+ if (firstKnowlegePiece === undefined || firstKnowlegeIndex === undefined) {
4255
+ return ''; // <- Note: Np knowledge present, return empty string
4256
+ }
4257
+ try {
4258
+ // TODO: [🚐] Make arrayable LLMs -> single LLM DRY
4259
+ const _llms = arrayableToArray(tools.llm);
4260
+ const llmTools = _llms.length === 1 ? _llms[0] : joinLlmExecutionTools(..._llms);
4261
+ const taskEmbeddingPrompt = {
4262
+ title: 'Knowledge Search',
4263
+ modelRequirements: {
4264
+ modelVariant: 'EMBEDDING',
4265
+ modelName: firstKnowlegeIndex.modelName,
4266
+ },
4267
+ content: task.content,
4268
+ parameters,
4269
+ };
4270
+ const taskEmbeddingResult = await llmTools.callEmbeddingModel(taskEmbeddingPrompt);
4271
+ const knowledgePiecesWithRelevance = preparedPipeline.knowledgePieces.map((knowledgePiece) => {
4272
+ const { index } = knowledgePiece;
4273
+ const knowledgePieceIndex = index.find((i) => i.modelName === firstKnowlegeIndex.modelName);
4274
+ // <- TODO: Do not use just first knowledge piece and first index to determine embedding model
4275
+ if (knowledgePieceIndex === undefined) {
4276
+ return {
4277
+ content: knowledgePiece.content,
4278
+ relevance: 0,
4279
+ };
4280
+ }
4281
+ const relevance = computeCosineSimilarity(knowledgePieceIndex.position, taskEmbeddingResult.content);
4282
+ return {
4283
+ content: knowledgePiece.content,
4284
+ relevance,
4285
+ };
4286
+ });
4287
+ const knowledgePiecesSorted = knowledgePiecesWithRelevance.sort((a, b) => a.relevance - b.relevance);
4288
+ const knowledgePiecesLimited = knowledgePiecesSorted.slice(0, 5);
4289
+ console.log('!!! Embedding', {
4290
+ task,
4291
+ taskEmbeddingPrompt,
4292
+ taskEmbeddingResult,
4293
+ firstKnowlegePiece,
4294
+ firstKnowlegeIndex,
4295
+ knowledgePiecesWithRelevance,
4296
+ knowledgePiecesSorted,
4297
+ knowledgePiecesLimited,
4298
+ });
4299
+ return knowledgePiecesToString(knowledgePiecesLimited);
4300
+ }
4301
+ catch (error) {
4302
+ assertsError(error);
4303
+ console.error('Error in `getKnowledgeForTask`', error);
4304
+ // Note: If the LLM fails, just return all knowledge pieces
4305
+ return knowledgePiecesToString(preparedPipeline.knowledgePieces);
4306
+ }
4085
4307
  }
4308
+ /**
4309
+ * TODO: !!!! Verify if this is working
4310
+ * TODO: [♨] Implement Better - use keyword search
4311
+ * TODO: [♨] Examples of values
4312
+ */
4086
4313
 
4087
4314
  /**
4088
- * @@@
4315
+ * Retrieves all reserved parameters for a given pipeline task, including context, knowledge, examples, and metadata.
4316
+ * Ensures all reserved parameters are defined and throws if any are missing.
4317
+ *
4318
+ * @param options - Options including tools, pipeline, task, and context.
4319
+ * @returns An object containing all reserved parameters for the task.
4089
4320
  *
4090
4321
  * @private internal utility of `createPipelineExecutor`
4091
4322
  */
4092
4323
  async function getReservedParametersForTask(options) {
4093
- const { preparedPipeline, task, pipelineIdentification } = options;
4324
+ const { tools, preparedPipeline, task, parameters, pipelineIdentification } = options;
4094
4325
  const context = await getContextForTask(); // <- [🏍]
4095
- const knowledge = await getKnowledgeForTask({ preparedPipeline, task });
4326
+ const knowledge = await getKnowledgeForTask({ tools, preparedPipeline, task, parameters });
4096
4327
  const examples = await getExamplesForTask();
4097
4328
  const currentDate = new Date().toISOString(); // <- TODO: [🧠][💩] Better
4098
4329
  const modelName = RESERVED_PARAMETER_MISSING_VALUE;
@@ -4118,23 +4349,21 @@ async function getReservedParametersForTask(options) {
4118
4349
  }
4119
4350
 
4120
4351
  /**
4121
- * @@@
4352
+ * Executes a single task within a pipeline, handling parameter validation, error checking, and progress reporting.
4353
+ *
4354
+ * @param options - Options for execution, including the task, pipeline, parameters, and callbacks.
4355
+ * @returns The output parameters produced by the task.
4122
4356
  *
4123
4357
  * @private internal utility of `createPipelineExecutor`
4124
4358
  */
4125
4359
  async function executeTask(options) {
4126
4360
  const { currentTask, preparedPipeline, parametersToPass, tools, onProgress, $executionReport, pipelineIdentification, maxExecutionAttempts, maxParallelCount, csvSettings, isVerbose, rootDirname, cacheDirname, intermediateFilesStrategy, isAutoInstalled, isNotPreparedWarningSupressed, } = options;
4127
4361
  const priority = preparedPipeline.tasks.length - preparedPipeline.tasks.indexOf(currentTask);
4128
- await onProgress({
4129
- outputParameters: {
4130
- [currentTask.resultingParameterName]: '', // <- TODO: [🧠] What is the best value here?
4131
- },
4132
- });
4133
4362
  // Note: Check consistency of used and dependent parameters which was also done in `validatePipeline`, but it’s good to doublecheck
4134
4363
  const usedParameterNames = extractParameterNamesFromTask(currentTask);
4135
4364
  const dependentParameterNames = new Set(currentTask.dependentParameterNames);
4136
4365
  // TODO: [👩🏾‍🤝‍👩🏻] Use here `mapAvailableToExpectedParameters`
4137
- if (union(difference(usedParameterNames, dependentParameterNames), difference(dependentParameterNames, usedParameterNames)).size !== 0) {
4366
+ if (difference(union(difference(usedParameterNames, dependentParameterNames), difference(dependentParameterNames, usedParameterNames)), new Set(RESERVED_PARAMETER_NAMES)).size !== 0) {
4138
4367
  throw new UnexpectedError(spaceTrim$1((block) => `
4139
4368
  Dependent parameters are not consistent with used parameters:
4140
4369
 
@@ -4154,9 +4383,11 @@ async function executeTask(options) {
4154
4383
  }
4155
4384
  const definedParameters = Object.freeze({
4156
4385
  ...(await getReservedParametersForTask({
4386
+ tools,
4157
4387
  preparedPipeline,
4158
4388
  task: currentTask,
4159
4389
  pipelineIdentification,
4390
+ parameters: parametersToPass,
4160
4391
  })),
4161
4392
  ...parametersToPass,
4162
4393
  });
@@ -4202,6 +4433,7 @@ async function executeTask(options) {
4202
4433
  preparedPipeline,
4203
4434
  tools,
4204
4435
  $executionReport,
4436
+ onProgress,
4205
4437
  pipelineIdentification,
4206
4438
  maxExecutionAttempts,
4207
4439
  maxParallelCount,
@@ -4229,7 +4461,8 @@ async function executeTask(options) {
4229
4461
  */
4230
4462
 
4231
4463
  /**
4232
- * @@@
4464
+ * Filters and returns only the output parameters from the provided pipeline execution options.
4465
+ * Adds warnings for any expected output parameters that are missing.
4233
4466
  *
4234
4467
  * @private internal utility of `createPipelineExecutor`
4235
4468
  */
@@ -4254,9 +4487,12 @@ function filterJustOutputParameters(options) {
4254
4487
  }
4255
4488
 
4256
4489
  /**
4257
- * @@@
4490
+ * Executes an entire pipeline, resolving tasks in dependency order, handling errors, and reporting progress.
4491
+ *
4492
+ * Note: This is not a `PipelineExecutor` (which is bound to a single pipeline), but a utility function used by `createPipelineExecutor` to create a `PipelineExecutor`.
4258
4493
  *
4259
- * Note: This is not a `PipelineExecutor` (which is binded with one exact pipeline), but a utility function of `createPipelineExecutor` which creates `PipelineExecutor`
4494
+ * @param options - Options for execution, including input parameters, pipeline, and callbacks.
4495
+ * @returns The result of the pipeline execution, including output parameters, errors, and usage statistics.
4260
4496
  *
4261
4497
  * @private internal utility of `createPipelineExecutor`
4262
4498
  */
@@ -4579,6 +4815,22 @@ function createPipelineExecutor(options) {
4579
4815
  cacheDirname,
4580
4816
  intermediateFilesStrategy,
4581
4817
  isAutoInstalled,
4818
+ }).catch((error) => {
4819
+ assertsError(error);
4820
+ return exportJson({
4821
+ name: 'pipelineExecutorResult',
4822
+ message: `Unuccessful PipelineExecutorResult, last catch`,
4823
+ order: [],
4824
+ value: {
4825
+ isSuccessful: false,
4826
+ errors: [serializeError(error)],
4827
+ warnings: [],
4828
+ usage: UNCERTAIN_USAGE,
4829
+ executionReport: null,
4830
+ outputParameters: {},
4831
+ preparedPipeline,
4832
+ },
4833
+ });
4582
4834
  });
4583
4835
  };
4584
4836
  const pipelineExecutor = (inputParameters) => createTask({
@@ -4710,27 +4962,48 @@ async function preparePersona(personaDescription, tools, options) {
4710
4962
  pipeline: await collection.getPipelineByUrl('https://promptbook.studio/promptbook/prepare-persona.book'),
4711
4963
  tools,
4712
4964
  });
4713
- // TODO: [🚐] Make arrayable LLMs -> single LLM DRY
4714
4965
  const _llms = arrayableToArray(tools.llm);
4715
4966
  const llmTools = _llms.length === 1 ? _llms[0] : joinLlmExecutionTools(..._llms);
4716
- const availableModels = await llmTools.listModels();
4717
- const availableModelNames = availableModels
4967
+ const availableModels = (await llmTools.listModels())
4718
4968
  .filter(({ modelVariant }) => modelVariant === 'CHAT')
4719
- .map(({ modelName }) => modelName)
4720
- .join(',');
4721
- const result = await preparePersonaExecutor({ availableModelNames, personaDescription }).asPromise();
4969
+ .map(({ modelName, modelDescription }) => ({
4970
+ modelName,
4971
+ modelDescription,
4972
+ // <- Note: `modelTitle` and `modelVariant` is not relevant for this task
4973
+ }));
4974
+ const result = await preparePersonaExecutor({
4975
+ availableModels /* <- Note: Passing as JSON */,
4976
+ personaDescription,
4977
+ }).asPromise();
4722
4978
  const { outputParameters } = result;
4723
- const { modelRequirements: modelRequirementsRaw } = outputParameters;
4724
- const modelRequirements = JSON.parse(modelRequirementsRaw);
4979
+ const { modelsRequirements: modelsRequirementsJson } = outputParameters;
4980
+ let modelsRequirementsUnchecked = jsonParse(modelsRequirementsJson);
4725
4981
  if (isVerbose) {
4726
- console.info(`PERSONA ${personaDescription}`, modelRequirements);
4982
+ console.info(`PERSONA ${personaDescription}`, modelsRequirementsUnchecked);
4727
4983
  }
4728
- const { modelName, systemMessage, temperature } = modelRequirements;
4729
- return {
4984
+ if (!Array.isArray(modelsRequirementsUnchecked)) {
4985
+ // <- TODO: Book should have syntax and system to enforce shape of JSON
4986
+ modelsRequirementsUnchecked = [modelsRequirementsUnchecked];
4987
+ /*
4988
+ throw new UnexpectedError(
4989
+ spaceTrim(
4990
+ (block) => `
4991
+ Invalid \`modelsRequirements\`:
4992
+
4993
+ \`\`\`json
4994
+ ${block(JSON.stringify(modelsRequirementsUnchecked, null, 4))}
4995
+ \`\`\`
4996
+ `,
4997
+ ),
4998
+ );
4999
+ */
5000
+ }
5001
+ const modelsRequirements = modelsRequirementsUnchecked.map((modelRequirements) => ({
4730
5002
  modelVariant: 'CHAT',
4731
- modelName,
4732
- systemMessage,
4733
- temperature,
5003
+ ...modelRequirements,
5004
+ }));
5005
+ return {
5006
+ modelsRequirements,
4734
5007
  };
4735
5008
  }
4736
5009
  /**
@@ -4741,7 +5014,8 @@ async function preparePersona(personaDescription, tools, options) {
4741
5014
  */
4742
5015
 
4743
5016
  /**
4744
- * @@@
5017
+ * Safely retrieves the global scope object (window in browser, global in Node.js)
5018
+ * regardless of the JavaScript environment in which the code is running
4745
5019
  *
4746
5020
  * Note: `$` is used to indicate that this function is not a pure function - it access global scope
4747
5021
  *
@@ -4752,10 +5026,10 @@ function $getGlobalScope() {
4752
5026
  }
4753
5027
 
4754
5028
  /**
4755
- * @@@
5029
+ * Normalizes a text string to SCREAMING_CASE (all uppercase with underscores).
4756
5030
  *
4757
- * @param text @@@
4758
- * @returns @@@
5031
+ * @param text The text string to be converted to SCREAMING_CASE format.
5032
+ * @returns The normalized text in SCREAMING_CASE format.
4759
5033
  * @example 'HELLO_WORLD'
4760
5034
  * @example 'I_LOVE_PROMPTBOOK'
4761
5035
  * @public exported from `@promptbook/utils`
@@ -4807,10 +5081,10 @@ function normalizeTo_SCREAMING_CASE(text) {
4807
5081
  */
4808
5082
 
4809
5083
  /**
4810
- * @@@
5084
+ * Normalizes a text string to snake_case format.
4811
5085
  *
4812
- * @param text @@@
4813
- * @returns @@@
5086
+ * @param text The text string to be converted to snake_case format.
5087
+ * @returns The normalized text in snake_case format.
4814
5088
  * @example 'hello_world'
4815
5089
  * @example 'i_love_promptbook'
4816
5090
  * @public exported from `@promptbook/utils`
@@ -4820,11 +5094,11 @@ function normalizeTo_snake_case(text) {
4820
5094
  }
4821
5095
 
4822
5096
  /**
4823
- * Register is @@@
5097
+ * Global registry for storing and managing registered entities of a given type.
4824
5098
  *
4825
5099
  * Note: `$` is used to indicate that this function is not a pure function - it accesses and adds variables in global scope.
4826
5100
  *
4827
- * @private internal utility, exported are only signleton instances of this class
5101
+ * @private internal utility, exported are only singleton instances of this class
4828
5102
  */
4829
5103
  class $Register {
4830
5104
  constructor(registerName) {
@@ -4868,10 +5142,10 @@ class $Register {
4868
5142
  }
4869
5143
 
4870
5144
  /**
4871
- * @@@
5145
+ * Global registry for storing metadata about all available scrapers and converters.
4872
5146
  *
4873
- * Note: `$` is used to indicate that this interacts with the global scope
4874
- * @singleton Only one instance of each register is created per build, but thare can be more @@@
5147
+ * Note: `$` is used to indicate that this interacts with the global scope.
5148
+ * @singleton Only one instance of each register is created per build, but there can be more in different contexts (e.g., tests).
4875
5149
  * @public exported from `@promptbook/core`
4876
5150
  */
4877
5151
  const $scrapersMetadataRegister = new $Register('scrapers_metadata');
@@ -4880,10 +5154,11 @@ const $scrapersMetadataRegister = new $Register('scrapers_metadata');
4880
5154
  */
4881
5155
 
4882
5156
  /**
4883
- * @@@
5157
+ * Registry for all available scrapers in the system.
5158
+ * Central point for registering and accessing different types of content scrapers.
4884
5159
  *
4885
5160
  * Note: `$` is used to indicate that this interacts with the global scope
4886
- * @singleton Only one instance of each register is created per build, but thare can be more @@@
5161
+ * @singleton Only one instance of each register is created per build, but there can be more than one in different build modules
4887
5162
  * @public exported from `@promptbook/core`
4888
5163
  */
4889
5164
  const $scrapersRegister = new $Register('scraper_constructors');
@@ -4979,10 +5254,10 @@ function $registeredScrapersMessage(availableScrapers) {
4979
5254
  */
4980
5255
 
4981
5256
  /**
4982
- * @@@
5257
+ * Converts a given text to kebab-case format.
4983
5258
  *
4984
- * @param text @@@
4985
- * @returns @@@
5259
+ * @param text The text to be converted.
5260
+ * @returns The kebab-case formatted string.
4986
5261
  * @example 'hello-world'
4987
5262
  * @example 'i-love-promptbook'
4988
5263
  * @public exported from `@promptbook/utils`
@@ -5051,7 +5326,8 @@ function knowledgeSourceContentToName(knowledgeSourceContent) {
5051
5326
  */
5052
5327
 
5053
5328
  /**
5054
- * @@@
5329
+ * Converts a name to a properly formatted subfolder path for cache storage.
5330
+ * Handles normalization and path formatting to create consistent cache directory structures.
5055
5331
  *
5056
5332
  * @private for `FileCacheStorage`
5057
5333
  */
@@ -5131,11 +5407,11 @@ function removeEmojis(text) {
5131
5407
  }
5132
5408
 
5133
5409
  /**
5134
- * @@@
5410
+ * Converts a title string into a normalized name.
5135
5411
  *
5136
- * @param value @@@
5137
- * @returns @@@
5138
- * @example @@@
5412
+ * @param value The title string to be converted to a name.
5413
+ * @returns A normalized name derived from the input title.
5414
+ * @example 'Hello World!' -> 'hello-world'
5139
5415
  * @public exported from `@promptbook/utils`
5140
5416
  */
5141
5417
  function titleToName(value) {
@@ -5186,7 +5462,9 @@ const promptbookFetch = async (urlOrRequest, init) => {
5186
5462
  */
5187
5463
 
5188
5464
  /**
5189
- * @@@
5465
+ * Factory function that creates a handler for processing knowledge sources.
5466
+ * Provides standardized processing of different types of knowledge sources
5467
+ * across various scraper implementations.
5190
5468
  *
5191
5469
  * @public exported from `@promptbook/core`
5192
5470
  */
@@ -5293,7 +5571,7 @@ async function makeKnowledgeSourceHandler(knowledgeSource, tools, options) {
5293
5571
  > },
5294
5572
  */
5295
5573
  async asJson() {
5296
- return JSON.parse(await tools.fs.readFile(filename, 'utf-8'));
5574
+ return jsonParse(await tools.fs.readFile(filename, 'utf-8'));
5297
5575
  },
5298
5576
  async asText() {
5299
5577
  return await tools.fs.readFile(filename, 'utf-8');
@@ -5427,9 +5705,12 @@ TODO: [🧊] This is how it can look in future
5427
5705
  */
5428
5706
 
5429
5707
  /**
5430
- * @@@
5708
+ * Prepares tasks by adding knowledge to the prompt and ensuring all necessary parameters are included.
5431
5709
  *
5432
- * @public exported from `@promptbook/core`
5710
+ * @param tasks Sequence of tasks that are chained together to form a pipeline
5711
+ * @returns A promise that resolves to the prepared tasks.
5712
+ *
5713
+ * @private internal utility of `preparePipeline`
5433
5714
  */
5434
5715
  async function prepareTasks(pipeline, tools, options) {
5435
5716
  const { maxParallelCount = DEFAULT_MAX_PARALLEL_COUNT } = options;
@@ -5551,14 +5832,14 @@ async function preparePipeline(pipeline, tools, options) {
5551
5832
  // TODO: [🖌][🧠] Implement some `mapAsync` function
5552
5833
  const preparedPersonas = new Array(personas.length);
5553
5834
  await forEachAsync(personas, { maxParallelCount /* <- TODO: [🪂] When there are subtasks, this maximul limit can be broken */ }, async (persona, index) => {
5554
- const modelRequirements = await preparePersona(persona.description, { ...tools, llm: llmToolsWithUsage }, {
5835
+ const { modelsRequirements } = await preparePersona(persona.description, { ...tools, llm: llmToolsWithUsage }, {
5555
5836
  rootDirname,
5556
5837
  maxParallelCount /* <- TODO: [🪂] */,
5557
5838
  isVerbose,
5558
5839
  });
5559
5840
  const preparedPersona = {
5560
5841
  ...persona,
5561
- modelRequirements,
5842
+ modelsRequirements,
5562
5843
  preparationIds: [/* TODO: [🧊] -> */ currentPreparation.id],
5563
5844
  // <- TODO: [🍙] Make some standard order of json properties
5564
5845
  };
@@ -5947,7 +6228,7 @@ const sectionCommandParser = {
5947
6228
  /**
5948
6229
  * Parses the boilerplate command
5949
6230
  *
5950
- * Note: @@@ This command is used as boilerplate for new commands - it should NOT be used in any `.book` file
6231
+ * Note: @@ This command is used as boilerplate for new commands - it should NOT be used in any `.book` file
5951
6232
  *
5952
6233
  * @see `documentationUrl` for more details
5953
6234
  * @private within the commands folder
@@ -6335,11 +6616,11 @@ const expectCommandParser = {
6335
6616
  };
6336
6617
 
6337
6618
  /**
6338
- * @@@
6619
+ * Normalizes a given text to camelCase format.
6339
6620
  *
6340
- * @param text @@@
6341
- * @param _isFirstLetterCapital @@@
6342
- * @returns @@@
6621
+ * @param text The text to be normalized.
6622
+ * @param _isFirstLetterCapital Whether the first letter should be capitalized.
6623
+ * @returns The camelCase formatted string.
6343
6624
  * @example 'helloWorld'
6344
6625
  * @example 'iLovePromptbook'
6345
6626
  * @public exported from `@promptbook/utils`
@@ -6410,11 +6691,12 @@ function removeQuotes(text) {
6410
6691
  }
6411
6692
 
6412
6693
  /**
6413
- * Function `validateParameterName` will @@@
6694
+ * Function `validateParameterName` will normalize and validate a parameter name for use in pipelines.
6695
+ * It removes diacritics, emojis, and quotes, normalizes to camelCase, and checks for reserved names and invalid characters.
6414
6696
  *
6415
- * @param parameterName @@@
6416
- * @returns @@@
6417
- * @throws {ParseError} @@@
6697
+ * @param parameterName The parameter name to validate and normalize.
6698
+ * @returns The validated and normalized parameter name.
6699
+ * @throws {ParseError} If the parameter name is empty, reserved, or contains invalid characters.
6418
6700
  * @private within the repository
6419
6701
  */
6420
6702
  function validateParameterName(parameterName) {
@@ -6484,8 +6766,6 @@ function validateParameterName(parameterName) {
6484
6766
  /**
6485
6767
  * Parses the foreach command
6486
6768
  *
6487
- * Note: @@@ This command is used as foreach for new commands - it should NOT be used in any `.book` file
6488
- *
6489
6769
  * @see `documentationUrl` for more details
6490
6770
  * @public exported from `@promptbook/editable`
6491
6771
  */
@@ -6542,14 +6822,14 @@ const foreachCommandParser = {
6542
6822
  `));
6543
6823
  // <- TODO: [🏢] List all supported format names
6544
6824
  }
6545
- const subvalueDefinition = formatDefinition.subvalueDefinitions.find((subvalueDefinition) => [subvalueDefinition.subvalueName, ...(subvalueDefinition.aliases || [])].includes(subformatName));
6546
- if (subvalueDefinition === undefined) {
6825
+ const subvalueParser = formatDefinition.subvalueParsers.find((subvalueParser) => [subvalueParser.subvalueName, ...(subvalueParser.aliases || [])].includes(subformatName));
6826
+ if (subvalueParser === undefined) {
6547
6827
  throw new ParseError(spaceTrim((block) => `
6548
6828
  Unsupported subformat name "${subformatName}" for format "${formatName}"
6549
6829
 
6550
6830
  Available subformat names for format "${formatDefinition.formatName}":
6551
- ${block(formatDefinition.subvalueDefinitions
6552
- .map((subvalueDefinition) => subvalueDefinition.subvalueName)
6831
+ ${block(formatDefinition.subvalueParsers
6832
+ .map((subvalueParser) => subvalueParser.subvalueName)
6553
6833
  .map((subvalueName) => `- ${subvalueName}`)
6554
6834
  .join('\n'))}
6555
6835
  `));
@@ -6726,14 +7006,14 @@ const formatCommandParser = {
6726
7006
  };
6727
7007
 
6728
7008
  /**
6729
- * @@@
7009
+ * Chatbot form factor definition for conversational interfaces that interact with users in a chat-like manner.
6730
7010
  *
6731
7011
  * @public exported from `@promptbook/core`
6732
7012
  */
6733
7013
  const ChatbotFormfactorDefinition = {
6734
7014
  name: 'CHATBOT',
6735
7015
  aliasNames: ['CHAT'],
6736
- description: `@@@`,
7016
+ description: `A chatbot form factor for conversational user interfaces.`,
6737
7017
  documentationUrl: `https://github.com/webgptorg/promptbook/discussions/174`,
6738
7018
  pipelineInterface: {
6739
7019
  inputParameters: [
@@ -6760,7 +7040,45 @@ const ChatbotFormfactorDefinition = {
6760
7040
  };
6761
7041
 
6762
7042
  /**
6763
- * Generator is form of app that @@@
7043
+ * Completion is formfactor that emulates completion models
7044
+ *
7045
+ * @public exported from `@promptbook/core`
7046
+ */
7047
+ const CompletionFormfactorDefinition = {
7048
+ name: 'COMPLETION',
7049
+ description: `Completion is formfactor that emulates completion models`,
7050
+ documentationUrl: `https://github.com/webgptorg/promptbook/discussions/@@`,
7051
+ // <- TODO: https://github.com/webgptorg/promptbook/discussions/new?category=concepts
7052
+ // "🔠 Completion Formfactor"
7053
+ pipelineInterface: {
7054
+ inputParameters: [
7055
+ {
7056
+ name: 'inputText',
7057
+ description: `Input text to be completed`,
7058
+ isInput: true,
7059
+ isOutput: false,
7060
+ },
7061
+ {
7062
+ name: 'instructions',
7063
+ description: `Additional instructions for the model, for example the required length, empty by default`,
7064
+ isInput: true,
7065
+ isOutput: false,
7066
+ },
7067
+ ],
7068
+ outputParameters: [
7069
+ {
7070
+ name: 'followingText',
7071
+ description: `Text that follows the input text`,
7072
+ isInput: false,
7073
+ isOutput: true,
7074
+ },
7075
+ ],
7076
+ },
7077
+ };
7078
+
7079
+ /**
7080
+ * Generator form factor represents an application that generates content or data based on user input or predefined rules.
7081
+ * This form factor is used for apps that produce outputs, such as text, images, or other media, based on provided input.
6764
7082
  *
6765
7083
  * @public exported from `@promptbook/core`
6766
7084
  */
@@ -6789,7 +7107,7 @@ const GeneratorFormfactorDefinition = {
6789
7107
  };
6790
7108
 
6791
7109
  /**
6792
- * @@@
7110
+ * Pipeline interface which is equivalent to `any`
6793
7111
  *
6794
7112
  * @see https://github.com/webgptorg/promptbook/discussions/171
6795
7113
  *
@@ -6804,13 +7122,13 @@ const GENERIC_PIPELINE_INTERFACE = {
6804
7122
  */
6805
7123
 
6806
7124
  /**
6807
- * @@@
7125
+ * A generic pipeline
6808
7126
  *
6809
7127
  * @public exported from `@promptbook/core`
6810
7128
  */
6811
7129
  const GenericFormfactorDefinition = {
6812
7130
  name: 'GENERIC',
6813
- description: `@@@`,
7131
+ description: `A generic pipeline`,
6814
7132
  documentationUrl: `https://github.com/webgptorg/promptbook/discussions/173`,
6815
7133
  pipelineInterface: GENERIC_PIPELINE_INTERFACE,
6816
7134
  };
@@ -6845,17 +7163,20 @@ const ImageGeneratorFormfactorDefinition = {
6845
7163
  };
6846
7164
 
6847
7165
  /**
6848
- * Matcher is form of app that @@@
7166
+ * Matcher is form of app that evaluates (spreadsheet) content against defined criteria or patterns,
7167
+ * determining if it matches or meets specific requirements. Used for classification,
7168
+ * validation, filtering, and quality assessment of inputs.
6849
7169
  *
6850
7170
  * @public exported from `@promptbook/core`
6851
7171
  */
6852
7172
  const MatcherFormfactorDefinition = {
6853
7173
  name: 'EXPERIMENTAL_MATCHER',
6854
- description: `@@@`,
7174
+ description: `An evaluation system that determines whether content meets specific criteria or patterns.
7175
+ Used for content validation, quality assessment, and intelligent filtering tasks. Currently in experimental phase.`,
6855
7176
  documentationUrl: `https://github.com/webgptorg/promptbook/discussions/177`,
6856
7177
  pipelineInterface: {
6857
7178
  inputParameters: [
6858
- /* @@@ */
7179
+ /* Input parameters for content to be matched and criteria to match against */
6859
7180
  {
6860
7181
  name: 'nonce',
6861
7182
  description: 'Just to prevent EXPERIMENTAL_MATCHER to be set as implicit formfactor',
@@ -6864,20 +7185,21 @@ const MatcherFormfactorDefinition = {
6864
7185
  },
6865
7186
  ],
6866
7187
  outputParameters: [
6867
- /* @@@ */
7188
+ /* Output parameters containing match results, confidence scores, and relevant metadata */
6868
7189
  ],
6869
7190
  },
6870
7191
  };
6871
7192
 
6872
7193
  /**
6873
- * Sheets is form of app that @@@
7194
+ * Sheets is form of app that processes tabular data in CSV format, allowing transformation
7195
+ * and analysis of structured data through AI-powered operations
6874
7196
  *
6875
7197
  * @public exported from `@promptbook/core`
6876
7198
  */
6877
7199
  const SheetsFormfactorDefinition = {
6878
7200
  name: 'SHEETS',
6879
7201
  aliasNames: ['SHEETS', 'SHEET'],
6880
- description: `@@@`,
7202
+ description: `A formfactor for processing spreadsheet-like data in CSV format, enabling AI transformations on tabular data`,
6881
7203
  documentationUrl: `https://github.com/webgptorg/promptbook/discussions/176`,
6882
7204
  pipelineInterface: {
6883
7205
  inputParameters: [
@@ -6900,13 +7222,16 @@ const SheetsFormfactorDefinition = {
6900
7222
  };
6901
7223
 
6902
7224
  /**
6903
- * Translator is form of app that @@@
7225
+ * Translator is form of app that transforms input text from one form to another,
7226
+ * such as language translation, style conversion, tone modification, or other text transformations.
6904
7227
  *
6905
7228
  * @public exported from `@promptbook/core`
6906
7229
  */
6907
7230
  const TranslatorFormfactorDefinition = {
6908
7231
  name: 'TRANSLATOR',
6909
- description: `@@@`,
7232
+ description: `A text transformation system that converts input content into different forms,
7233
+ including language translations, paraphrasing, style conversions, and tone adjustments.
7234
+ This form factor takes one input and produces one transformed output.`,
6910
7235
  documentationUrl: `https://github.com/webgptorg/promptbook/discussions/175`,
6911
7236
  pipelineInterface: {
6912
7237
  inputParameters: [
@@ -6943,6 +7268,8 @@ const FORMFACTOR_DEFINITIONS = [
6943
7268
  MatcherFormfactorDefinition,
6944
7269
  GeneratorFormfactorDefinition,
6945
7270
  ImageGeneratorFormfactorDefinition,
7271
+ CompletionFormfactorDefinition,
7272
+ // <- [🛬] When making new formfactor, copy the _boilerplate and link it here
6946
7273
  ];
6947
7274
  /**
6948
7275
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -6951,7 +7278,7 @@ const FORMFACTOR_DEFINITIONS = [
6951
7278
  /**
6952
7279
  * Parses the formfactor command
6953
7280
  *
6954
- * Note: @@@ This command is used as formfactor for new commands - it should NOT be used in any `.book` file
7281
+ * Note: This command is used as a formfactor for new commands and defines the app type format - it should NOT be used in any `.book` file
6955
7282
  *
6956
7283
  * @see `documentationUrl` for more details
6957
7284
  * @public exported from `@promptbook/editable`
@@ -6973,7 +7300,7 @@ const formfactorCommandParser = {
6973
7300
  /**
6974
7301
  * Description of the FORMFACTOR command
6975
7302
  */
6976
- description: `@@`,
7303
+ description: `Specifies the application type and interface requirements that this promptbook should conform to`,
6977
7304
  /**
6978
7305
  * Link to documentation
6979
7306
  */
@@ -7116,8 +7443,7 @@ const jokerCommandParser = {
7116
7443
  };
7117
7444
 
7118
7445
  /**
7119
- * @@@
7120
- *
7446
+ * @see {@link ModelVariant}
7121
7447
  * @public exported from `@promptbook/core`
7122
7448
  */
7123
7449
  const MODEL_VARIANTS = ['COMPLETION', 'CHAT', 'EMBEDDING' /* <- TODO [🏳] */ /* <- [🤖] */];
@@ -7549,10 +7875,10 @@ function $applyToTaskJson(command, $taskJson, $pipelineJson) {
7549
7875
  }
7550
7876
 
7551
7877
  /**
7552
- * @@@
7878
+ * Checks if the given value is a valid JavaScript identifier name.
7553
7879
  *
7554
- * @param javascriptName @@@
7555
- * @returns @@@
7880
+ * @param javascriptName The value to check for JavaScript identifier validity.
7881
+ * @returns `true` if the value is a valid JavaScript name, false otherwise.
7556
7882
  * @public exported from `@promptbook/utils`
7557
7883
  */
7558
7884
  function isValidJavascriptName(javascriptName) {
@@ -8032,7 +8358,10 @@ function parseCommand(raw, usagePlace) {
8032
8358
  `));
8033
8359
  }
8034
8360
  /**
8035
- * @@@
8361
+ * Generates a markdown-formatted message listing all supported commands
8362
+ * with their descriptions and documentation links
8363
+ *
8364
+ * @returns A formatted markdown string containing all available commands and their details
8036
8365
  */
8037
8366
  function getSupportedCommandsMessage() {
8038
8367
  return COMMANDS.flatMap(({ name, aliasNames, description, documentationUrl }) =>
@@ -8043,7 +8372,10 @@ function getSupportedCommandsMessage() {
8043
8372
  ]).join('\n');
8044
8373
  }
8045
8374
  /**
8046
- * @@@
8375
+ * Attempts to parse a command variant using the provided input parameters
8376
+ *
8377
+ * @param input Object containing command parsing information including raw command text and normalized values
8378
+ * @returns A parsed Command object if successful, or null if the command cannot be parsed
8047
8379
  */
8048
8380
  function parseCommandVariant(input) {
8049
8381
  const { commandNameRaw, usagePlace, normalized, args, raw, rawArgs } = input;
@@ -8090,7 +8422,7 @@ function parseCommandVariant(input) {
8090
8422
  }
8091
8423
 
8092
8424
  /**
8093
- * @@@
8425
+ * Extracts the interface (input and output parameters) from a pipeline.
8094
8426
  *
8095
8427
  * @deprecated https://github.com/webgptorg/promptbook/pull/186
8096
8428
  * @see https://github.com/webgptorg/promptbook/discussions/171
@@ -8123,7 +8455,7 @@ function getPipelineInterface(pipeline) {
8123
8455
  }
8124
8456
 
8125
8457
  /**
8126
- * @@@
8458
+ * Checks if two pipeline interfaces are structurally identical.
8127
8459
  *
8128
8460
  * @deprecated https://github.com/webgptorg/promptbook/pull/186
8129
8461
  * @see https://github.com/webgptorg/promptbook/discussions/171
@@ -8155,10 +8487,11 @@ function isPipelineInterfacesEqual(pipelineInterface1, pipelineInterface2) {
8155
8487
  }
8156
8488
 
8157
8489
  /**
8158
- * @@@
8490
+ * Checks if a given pipeline satisfies the requirements of a specified pipeline interface.
8159
8491
  *
8160
8492
  * @deprecated https://github.com/webgptorg/promptbook/pull/186
8161
8493
  * @see https://github.com/webgptorg/promptbook/discussions/171
8494
+ * @returns `true` if the pipeline implements the interface, `false` otherwise.
8162
8495
  *
8163
8496
  * @public exported from `@promptbook/core`
8164
8497
  */
@@ -8344,7 +8677,8 @@ function removeMarkdownComments(content) {
8344
8677
  }
8345
8678
 
8346
8679
  /**
8347
- * @@@
8680
+ * Utility to determine if a pipeline string is in flat format.
8681
+ * A flat pipeline is a simple text without proper structure (headers, blocks, etc).
8348
8682
  *
8349
8683
  * @public exported from `@promptbook/editable`
8350
8684
  */
@@ -8365,7 +8699,10 @@ function isFlatPipeline(pipelineString) {
8365
8699
  }
8366
8700
 
8367
8701
  /**
8368
- * @@@
8702
+ * Converts a pipeline structure to its string representation.
8703
+ *
8704
+ * Transforms a flat, simple pipeline into a properly formatted pipeline string
8705
+ * with sections for title, prompt, and return statement.
8369
8706
  *
8370
8707
  * @public exported from `@promptbook/editable`
8371
8708
  */
@@ -8422,7 +8759,7 @@ function deflatePipeline(pipelineString) {
8422
8759
  * Note: It can not work with html syntax and comments
8423
8760
  *
8424
8761
  * @param markdown any valid markdown
8425
- * @returns @@@
8762
+ * @returns An array of strings, each representing an individual list item found in the markdown
8426
8763
  * @public exported from `@promptbook/markdown-utils`
8427
8764
  */
8428
8765
  function extractAllListItemsFromMarkdown(markdown) {
@@ -9257,7 +9594,8 @@ function $execCommand(options) {
9257
9594
  */
9258
9595
 
9259
9596
  /**
9260
- * @@@
9597
+ * Attempts to locate the specified application on a Linux system using the 'which' command.
9598
+ * Returns the path to the executable if found, or null otherwise.
9261
9599
  *
9262
9600
  * @private within the repository
9263
9601
  */
@@ -9277,7 +9615,8 @@ async function locateAppOnLinux({ linuxWhich, }) {
9277
9615
  */
9278
9616
 
9279
9617
  /**
9280
- * @@@
9618
+ * Provides filesystem access (for example for Node.js-based scrapers)
9619
+ * Creates a standardized filesystem interface that scrapers can use for file operations.
9281
9620
  *
9282
9621
  * @public exported from `@promptbook/node`
9283
9622
  */
@@ -9323,7 +9662,8 @@ async function isExecutable(path, fs) {
9323
9662
  // eslint-disable-next-line @typescript-eslint/no-var-requires
9324
9663
  const userhome = require('userhome');
9325
9664
  /**
9326
- * @@@
9665
+ * Attempts to locate the specified application on a macOS system by checking standard application paths and using mdfind.
9666
+ * Returns the path to the executable if found, or null otherwise.
9327
9667
  *
9328
9668
  * @private within the repository
9329
9669
  */
@@ -9355,7 +9695,8 @@ async function locateAppOnMacOs({ macOsName, }) {
9355
9695
  */
9356
9696
 
9357
9697
  /**
9358
- * @@@
9698
+ * Attempts to locate the specified application on a Windows system by searching common installation directories.
9699
+ * Returns the path to the executable if found, or null otherwise.
9359
9700
  *
9360
9701
  * @private within the repository
9361
9702
  */
@@ -9426,7 +9767,8 @@ function locateApp(options) {
9426
9767
  */
9427
9768
 
9428
9769
  /**
9429
- * @@@
9770
+ * Locates the LibreOffice executable on the current system by searching platform-specific paths.
9771
+ * Returns the path to the executable if found, or null otherwise.
9430
9772
  *
9431
9773
  * @private within the repository
9432
9774
  */
@@ -9444,7 +9786,8 @@ function locateLibreoffice() {
9444
9786
  */
9445
9787
 
9446
9788
  /**
9447
- * @@@
9789
+ * Locates the Pandoc executable on the current system by searching platform-specific paths.
9790
+ * Returns the path to the executable if found, or null otherwise.
9448
9791
  *
9449
9792
  * @private within the repository
9450
9793
  */
@@ -9462,7 +9805,7 @@ function locatePandoc() {
9462
9805
  */
9463
9806
 
9464
9807
  /**
9465
- * @@@
9808
+ * Provides paths to required executables (i.e. as Pandoc and LibreOffice) for Node.js environments.
9466
9809
  *
9467
9810
  * @public exported from `@promptbook/node`
9468
9811
  */
@@ -9482,10 +9825,10 @@ async function $provideExecutablesForNode(options) {
9482
9825
  */
9483
9826
 
9484
9827
  /**
9485
- * @@@
9828
+ * Register for LLM tools metadata.
9486
9829
  *
9487
9830
  * Note: `$` is used to indicate that this interacts with the global scope
9488
- * @singleton Only one instance of each register is created per build, but thare can be more @@@
9831
+ * @singleton Only one instance of each register is created per build, but there can be more instances across different builds or environments.
9489
9832
  * @public exported from `@promptbook/core`
9490
9833
  */
9491
9834
  const $llmToolsMetadataRegister = new $Register('llm_tools_metadata');
@@ -9513,10 +9856,10 @@ function isRootPath(value) {
9513
9856
  */
9514
9857
 
9515
9858
  /**
9516
- * @@@
9859
+ * Register for LLM tools.
9517
9860
  *
9518
9861
  * Note: `$` is used to indicate that this interacts with the global scope
9519
- * @singleton Only one instance of each register is created per build, but thare can be more @@@
9862
+ * @singleton Only one instance of each register is created per build, but there can be more instances across different builds or environments.
9520
9863
  * @public exported from `@promptbook/core`
9521
9864
  */
9522
9865
  const $llmToolsRegister = new $Register('llm_execution_tools_constructors');
@@ -9709,9 +10052,8 @@ async function $provideEnvFilename() {
9709
10052
  */
9710
10053
 
9711
10054
  /**
9712
- * @@@
10055
+ * Provides LLM tools configuration by reading environment variables.
9713
10056
  *
9714
- * @@@ .env
9715
10057
  * Note: `$` is used to indicate that this function is not a pure function - it uses filesystem to access `.env` file
9716
10058
  *
9717
10059
  * It looks for environment variables:
@@ -9719,7 +10061,8 @@ async function $provideEnvFilename() {
9719
10061
  * - `process.env.ANTHROPIC_CLAUDE_API_KEY`
9720
10062
  * - ...
9721
10063
  *
9722
- * @returns @@@
10064
+ * @see Environment variables documentation or .env file for required variables.
10065
+ * @returns A promise that resolves to the LLM tools configuration, or null if configuration is incomplete or missing.
9723
10066
  * @public exported from `@promptbook/node`
9724
10067
  */
9725
10068
  async function $provideLlmToolsConfigurationFromEnv() {
@@ -9741,11 +10084,16 @@ async function $provideLlmToolsConfigurationFromEnv() {
9741
10084
  */
9742
10085
 
9743
10086
  /**
9744
- * @@@
10087
+ * Creates LLM execution tools from provided configuration objects
10088
+ *
10089
+ * Instantiates and configures LLM tool instances for each configuration entry,
10090
+ * combining them into a unified interface via MultipleLlmExecutionTools.
9745
10091
  *
9746
10092
  * Note: This function is not cached, every call creates new instance of `MultipleLlmExecutionTools`
9747
10093
  *
9748
- * @returns @@@
10094
+ * @param configuration Array of LLM tool configurations to instantiate
10095
+ * @param options Additional options for configuring the LLM tools
10096
+ * @returns A unified interface combining all successfully instantiated LLM tools
9749
10097
  * @public exported from `@promptbook/core`
9750
10098
  */
9751
10099
  function createLlmToolsFromConfiguration(configuration, options = {}) {
@@ -9784,7 +10132,11 @@ function createLlmToolsFromConfiguration(configuration, options = {}) {
9784
10132
  /**
9785
10133
  * TODO: [🎌] Together with `createLlmToolsFromConfiguration` + 'EXECUTION_TOOLS_CLASSES' gets to `@promptbook/core` ALL model providers, make this more efficient
9786
10134
  * TODO: [🧠][🎌] Dynamically install required providers
9787
- * TODO: @@@ write discussion about this - wizzard
10135
+ * TODO: We should implement an interactive configuration wizard that would:
10136
+ * 1. Detect which LLM providers are available in the environment
10137
+ * 2. Guide users through required configuration settings for each provider
10138
+ * 3. Allow testing connections before completing setup
10139
+ * 4. Generate appropriate configuration code for application integration
9788
10140
  * TODO: [🧠][🍛] Which name is better `createLlmToolsFromConfig` or `createLlmToolsFromConfiguration`?
9789
10141
  * TODO: [🧠] Is there some meaningfull way how to test this util
9790
10142
  * TODO: This should be maybe not under `_common` but under `utils`
@@ -9792,11 +10144,14 @@ function createLlmToolsFromConfiguration(configuration, options = {}) {
9792
10144
  */
9793
10145
 
9794
10146
  /**
9795
- * @@@
10147
+ * Automatically configures LLM tools from environment variables in Node.js
10148
+ *
10149
+ * This utility function detects available LLM providers based on environment variables
10150
+ * and creates properly configured LLM execution tools for each detected provider.
9796
10151
  *
9797
10152
  * Note: This function is not cached, every call creates new instance of `MultipleLlmExecutionTools`
9798
10153
  *
9799
- * @@@ .env
10154
+ * Supports environment variables from .env files when dotenv is configured
9800
10155
  * Note: `$` is used to indicate that this function is not a pure function - it uses filesystem to access `.env` file
9801
10156
  *
9802
10157
  * It looks for environment variables:
@@ -9804,7 +10159,8 @@ function createLlmToolsFromConfiguration(configuration, options = {}) {
9804
10159
  * - `process.env.ANTHROPIC_CLAUDE_API_KEY`
9805
10160
  * - ...
9806
10161
  *
9807
- * @returns @@@
10162
+ * @param options Configuration options for the LLM tools
10163
+ * @returns A unified interface containing all detected and configured LLM tools
9808
10164
  * @public exported from `@promptbook/node`
9809
10165
  */
9810
10166
  async function $provideLlmToolsFromEnv(options = {}) {
@@ -9830,7 +10186,16 @@ async function $provideLlmToolsFromEnv(options = {}) {
9830
10186
  return createLlmToolsFromConfiguration(configuration, options);
9831
10187
  }
9832
10188
  /**
9833
- * TODO: @@@ write `$provideLlmToolsFromEnv` vs `$provideLlmToolsConfigurationFromEnv` vs `createLlmToolsFromConfiguration`
10189
+ * TODO: The architecture for LLM tools configuration consists of three key functions:
10190
+ * 1. `$provideLlmToolsFromEnv` - High-level function that detects available providers from env vars and returns ready-to-use LLM tools
10191
+ * 2. `$provideLlmToolsConfigurationFromEnv` - Middle layer that extracts configuration objects from environment variables
10192
+ * 3. `createLlmToolsFromConfiguration` - Low-level function that instantiates LLM tools from explicit configuration
10193
+ *
10194
+ * This layered approach allows flexibility in how tools are configured:
10195
+ * - Use $provideLlmToolsFromEnv for automatic detection and setup in Node.js environments
10196
+ * - Use $provideLlmToolsConfigurationFromEnv to extract config objects for modification before instantiation
10197
+ * - Use createLlmToolsFromConfiguration for explicit control over tool configurations
10198
+ *
9834
10199
  * TODO: [🧠][🍛] Which name is better `$provideLlmToolsFromEnv` or `$provideLlmToolsFromEnvironment`?
9835
10200
  * TODO: [🧠] Is there some meaningfull way how to test this util
9836
10201
  * Note: [🟢] Code in this file should never be never released in packages that could be imported into browser environment
@@ -9840,11 +10205,9 @@ async function $provideLlmToolsFromEnv(options = {}) {
9840
10205
  */
9841
10206
 
9842
10207
  /**
9843
- * @@@
9844
- *
9845
- * 1) @@@
9846
- * 2) @@@
9847
- *
10208
+ * Provides a collection of scrapers optimized for Node.js environment.
10209
+ * 1) `provideScrapersForNode` use as default
10210
+ * 2) `provideScrapersForBrowser` use in limited browser environment *
9848
10211
  * @public exported from `@promptbook/node`
9849
10212
  */
9850
10213
  async function $provideScrapersForNode(tools, options) {
@@ -9951,11 +10314,11 @@ function parseKeywordsFromString(input) {
9951
10314
  }
9952
10315
 
9953
10316
  /**
9954
- * @@@
10317
+ * Converts a name string into a URI-compatible format.
9955
10318
  *
9956
- * @param name @@@
9957
- * @returns @@@
9958
- * @example @@@
10319
+ * @param name The string to be converted to a URI-compatible format.
10320
+ * @returns A URI-compatible string derived from the input name.
10321
+ * @example 'Hello World' -> 'hello-world'
9959
10322
  * @public exported from `@promptbook/utils`
9960
10323
  */
9961
10324
  function nameToUriPart(name) {
@@ -9969,11 +10332,11 @@ function nameToUriPart(name) {
9969
10332
  }
9970
10333
 
9971
10334
  /**
9972
- * @@@
10335
+ * Converts a given name into URI-compatible parts.
9973
10336
  *
9974
- * @param name @@@
9975
- * @returns @@@
9976
- * @example @@@
10337
+ * @param name The name to be converted into URI parts.
10338
+ * @returns An array of URI-compatible parts derived from the name.
10339
+ * @example 'Example Name' -> ['example', 'name']
9977
10340
  * @public exported from `@promptbook/utils`
9978
10341
  */
9979
10342
  function nameToUriParts(name) {
@@ -10780,7 +11143,10 @@ function stringifyPipelineJson(pipeline) {
10780
11143
  */
10781
11144
 
10782
11145
  /**
10783
- * @@@
11146
+ * A storage implementation that caches data in files organized in a directory structure.
11147
+ * Provides methods for retrieving, storing, and managing cached data on the filesystem.
11148
+ *
11149
+ * This class implements the PromptbookStorage interface for filesystem-based caching.
10784
11150
  *
10785
11151
  * @public exported from `@promptbook/node`
10786
11152
  */
@@ -10793,7 +11159,8 @@ class FileCacheStorage {
10793
11159
  }
10794
11160
  }
10795
11161
  /**
10796
- * @@@
11162
+ * Converts a storage key to a filesystem path where the data should be stored.
11163
+ * Creates a consistent, deterministic file path based on the key string.
10797
11164
  */
10798
11165
  getFilenameForKey(key) {
10799
11166
  // TODO: [👬] DRY
@@ -10805,7 +11172,8 @@ class FileCacheStorage {
10805
11172
  ...nameToSubfolderPath(hash /* <- TODO: [🎎] Maybe add some SHA256 prefix */), `${name.substring(0, MAX_FILENAME_LENGTH)}.json`);
10806
11173
  }
10807
11174
  /**
10808
- * @@@ Returns the current value associated with the given key, or null if the given key does not exist in the list associated with the object.
11175
+ * Returns the current value associated with the given key, or null if the given key does not exist.
11176
+ * Retrieves the cached data from the file system storage.
10809
11177
  */
10810
11178
  async getItem(key) {
10811
11179
  const filename = this.getFilenameForKey(key);
@@ -10813,12 +11181,13 @@ class FileCacheStorage {
10813
11181
  return null;
10814
11182
  }
10815
11183
  const fileContent = await readFile(filename, 'utf-8');
10816
- const value = JSON.parse(fileContent);
11184
+ const value = jsonParse(fileContent);
10817
11185
  // TODO: [🌗]
10818
11186
  return value;
10819
11187
  }
10820
11188
  /**
10821
- * @@@ Sets the value of the pair identified by key to value, creating a new key/value pair if none existed for key previously.
11189
+ * Sets the value of the pair identified by key to value, creating a new key/value pair if none existed for key previously.
11190
+ * Persists data to the file system, creating necessary directory structure if it doesn't exist.
10822
11191
  */
10823
11192
  async setItem(key, value) {
10824
11193
  const filename = this.getFilenameForKey(key);
@@ -10830,7 +11199,8 @@ class FileCacheStorage {
10830
11199
  await writeFile(filename, fileContent, 'utf-8');
10831
11200
  }
10832
11201
  /**
10833
- * @@@ Removes the key/value pair with the given key from the list associated with the object, if a key/value pair with the given key exists.
11202
+ * Removes the key/value pair with the given key from the storage, if a key/value pair with the given key exists.
11203
+ * Deletes the corresponding file from the filesystem.
10834
11204
  */
10835
11205
  async removeItem(key) {
10836
11206
  const filename = this.getFilenameForKey(key);