@promptbook/javascript 0.92.0-8 → 0.92.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (207) hide show
  1. package/README.md +1 -5
  2. package/esm/index.es.js +522 -514
  3. package/esm/index.es.js.map +1 -1
  4. package/esm/typings/src/_packages/browser.index.d.ts +2 -0
  5. package/esm/typings/src/_packages/core.index.d.ts +26 -14
  6. package/esm/typings/src/_packages/types.index.d.ts +6 -2
  7. package/esm/typings/src/collection/PipelineCollection.d.ts +0 -2
  8. package/esm/typings/src/collection/SimplePipelineCollection.d.ts +1 -1
  9. package/esm/typings/src/commands/FOREACH/ForeachJson.d.ts +6 -6
  10. package/esm/typings/src/commands/FOREACH/foreachCommandParser.d.ts +0 -2
  11. package/esm/typings/src/commands/FORMFACTOR/formfactorCommandParser.d.ts +1 -1
  12. package/esm/typings/src/commands/_BOILERPLATE/boilerplateCommandParser.d.ts +1 -1
  13. package/esm/typings/src/commands/_common/types/CommandParser.d.ts +36 -28
  14. package/esm/typings/src/config.d.ts +41 -11
  15. package/esm/typings/src/constants.d.ts +43 -2
  16. package/esm/typings/src/conversion/parsePipeline.d.ts +2 -2
  17. package/esm/typings/src/errors/0-BoilerplateError.d.ts +2 -2
  18. package/esm/typings/src/errors/CollectionError.d.ts +1 -1
  19. package/esm/typings/src/executables/$provideExecutablesForNode.d.ts +1 -1
  20. package/esm/typings/src/executables/apps/locateLibreoffice.d.ts +2 -1
  21. package/esm/typings/src/executables/apps/locatePandoc.d.ts +2 -1
  22. package/esm/typings/src/executables/locateApp.d.ts +2 -2
  23. package/esm/typings/src/executables/platforms/locateAppOnLinux.d.ts +2 -1
  24. package/esm/typings/src/executables/platforms/locateAppOnMacOs.d.ts +2 -1
  25. package/esm/typings/src/executables/platforms/locateAppOnWindows.d.ts +2 -1
  26. package/esm/typings/src/execution/AbstractTaskResult.d.ts +1 -1
  27. package/esm/typings/src/execution/CommonToolsOptions.d.ts +5 -1
  28. package/esm/typings/src/execution/ExecutionTask.d.ts +19 -1
  29. package/esm/typings/src/execution/LlmExecutionToolsConstructor.d.ts +2 -1
  30. package/esm/typings/src/execution/PipelineExecutorResult.d.ts +4 -2
  31. package/esm/typings/src/execution/PromptbookFetch.d.ts +1 -1
  32. package/esm/typings/src/execution/ScriptExecutionTools.d.ts +1 -1
  33. package/esm/typings/src/execution/createPipelineExecutor/$OngoingTaskResult.d.ts +12 -9
  34. package/esm/typings/src/execution/createPipelineExecutor/10-executePipeline.d.ts +13 -10
  35. package/esm/typings/src/execution/createPipelineExecutor/20-executeTask.d.ts +12 -9
  36. package/esm/typings/src/execution/createPipelineExecutor/30-executeFormatSubvalues.d.ts +15 -3
  37. package/esm/typings/src/execution/createPipelineExecutor/40-executeAttempts.d.ts +21 -15
  38. package/esm/typings/src/execution/createPipelineExecutor/computeCosineSimilarity.d.ts +13 -0
  39. package/esm/typings/src/execution/createPipelineExecutor/filterJustOutputParameters.d.ts +7 -6
  40. package/esm/typings/src/execution/createPipelineExecutor/getContextForTask.d.ts +5 -1
  41. package/esm/typings/src/execution/createPipelineExecutor/getExamplesForTask.d.ts +1 -1
  42. package/esm/typings/src/execution/createPipelineExecutor/getKnowledgeForTask.d.ts +12 -9
  43. package/esm/typings/src/execution/createPipelineExecutor/getReservedParametersForTask.d.ts +18 -5
  44. package/esm/typings/src/execution/createPipelineExecutor/knowledgePiecesToString.d.ts +9 -0
  45. package/esm/typings/src/execution/execution-report/ExecutionReportJson.d.ts +1 -1
  46. package/esm/typings/src/execution/execution-report/ExecutionReportString.d.ts +1 -1
  47. package/esm/typings/src/execution/translation/automatic-translate/automatic-translators/LindatAutomaticTranslator.d.ts +4 -4
  48. package/esm/typings/src/execution/utils/checkExpectations.d.ts +3 -3
  49. package/esm/typings/src/execution/utils/uncertainNumber.d.ts +3 -2
  50. package/esm/typings/src/execution/utils/usageToWorktime.d.ts +1 -1
  51. package/esm/typings/src/formats/_common/{FormatDefinition.d.ts → FormatParser.d.ts} +8 -6
  52. package/esm/typings/src/formats/_common/FormatSubvalueParser.d.ts +66 -0
  53. package/esm/typings/src/formats/csv/CsvFormatParser.d.ts +17 -0
  54. package/esm/typings/src/formats/csv/CsvSettings.d.ts +2 -2
  55. package/esm/typings/src/formats/csv/utils/csvParse.d.ts +12 -0
  56. package/esm/typings/src/formats/csv/utils/isValidCsvString.d.ts +1 -1
  57. package/esm/typings/src/formats/index.d.ts +2 -2
  58. package/esm/typings/src/formats/json/JsonFormatParser.d.ts +19 -0
  59. package/esm/typings/src/formats/json/utils/isValidJsonString.d.ts +1 -1
  60. package/esm/typings/src/formats/json/utils/jsonParse.d.ts +0 -3
  61. package/esm/typings/src/formats/text/{TextFormatDefinition.d.ts → TextFormatParser.d.ts} +7 -7
  62. package/esm/typings/src/formats/xml/XmlFormatParser.d.ts +19 -0
  63. package/esm/typings/src/formats/xml/utils/isValidXmlString.d.ts +1 -1
  64. package/esm/typings/src/formfactors/_boilerplate/BoilerplateFormfactorDefinition.d.ts +3 -2
  65. package/esm/typings/src/formfactors/_common/AbstractFormfactorDefinition.d.ts +16 -7
  66. package/esm/typings/src/formfactors/_common/FormfactorDefinition.d.ts +3 -1
  67. package/esm/typings/src/formfactors/_common/string_formfactor_name.d.ts +2 -1
  68. package/esm/typings/src/formfactors/chatbot/ChatbotFormfactorDefinition.d.ts +2 -2
  69. package/esm/typings/src/formfactors/completion/CompletionFormfactorDefinition.d.ts +29 -0
  70. package/esm/typings/src/formfactors/generator/GeneratorFormfactorDefinition.d.ts +2 -1
  71. package/esm/typings/src/formfactors/generic/GenericFormfactorDefinition.d.ts +2 -2
  72. package/esm/typings/src/formfactors/index.d.ts +33 -8
  73. package/esm/typings/src/formfactors/matcher/MatcherFormfactorDefinition.d.ts +4 -2
  74. package/esm/typings/src/formfactors/sheets/SheetsFormfactorDefinition.d.ts +3 -2
  75. package/esm/typings/src/formfactors/translator/TranslatorFormfactorDefinition.d.ts +3 -2
  76. package/esm/typings/src/high-level-abstractions/index.d.ts +2 -2
  77. package/esm/typings/src/llm-providers/_common/register/$llmToolsMetadataRegister.d.ts +3 -3
  78. package/esm/typings/src/llm-providers/_common/register/$llmToolsRegister.d.ts +3 -3
  79. package/esm/typings/src/llm-providers/_common/register/$provideLlmToolsConfigurationFromEnv.d.ts +4 -4
  80. package/esm/typings/src/llm-providers/_common/register/$provideLlmToolsForTestingAndScriptsAndPlayground.d.ts +4 -3
  81. package/esm/typings/src/llm-providers/_common/register/$provideLlmToolsFromEnv.d.ts +18 -5
  82. package/esm/typings/src/llm-providers/_common/register/LlmToolsConfiguration.d.ts +11 -4
  83. package/esm/typings/src/llm-providers/_common/register/LlmToolsMetadata.d.ts +21 -42
  84. package/esm/typings/src/llm-providers/_common/register/LlmToolsOptions.d.ts +9 -2
  85. package/esm/typings/src/llm-providers/_common/register/createLlmToolsFromConfiguration.d.ts +13 -4
  86. package/esm/typings/src/llm-providers/_common/utils/cache/CacheItem.d.ts +10 -5
  87. package/esm/typings/src/llm-providers/_common/utils/cache/CacheLlmToolsOptions.d.ts +11 -3
  88. package/esm/typings/src/llm-providers/_common/utils/cache/cacheLlmTools.d.ts +3 -3
  89. package/esm/typings/src/llm-providers/_common/utils/count-total-usage/limitTotalUsage.d.ts +5 -5
  90. package/esm/typings/src/llm-providers/anthropic-claude/AnthropicClaudeExecutionTools.d.ts +6 -0
  91. package/esm/typings/src/llm-providers/anthropic-claude/anthropic-claude-models.d.ts +1 -1
  92. package/esm/typings/src/llm-providers/azure-openai/AzureOpenAiExecutionTools.d.ts +5 -1
  93. package/esm/typings/src/llm-providers/azure-openai/AzureOpenAiExecutionToolsOptions.d.ts +4 -4
  94. package/esm/typings/src/llm-providers/deepseek/deepseek-models.d.ts +1 -1
  95. package/esm/typings/src/llm-providers/google/google-models.d.ts +1 -1
  96. package/esm/typings/src/llm-providers/openai/OpenAiAssistantExecutionTools.d.ts +1 -1
  97. package/esm/typings/src/llm-providers/openai/OpenAiExecutionTools.d.ts +4 -0
  98. package/esm/typings/src/llm-providers/openai/openai-models.d.ts +1 -1
  99. package/esm/typings/src/llm-providers/openai/register-configuration.d.ts +2 -2
  100. package/esm/typings/src/llm-providers/openai/register-constructor.d.ts +2 -2
  101. package/esm/typings/src/migrations/migratePipeline.d.ts +9 -0
  102. package/esm/typings/src/other/templates/getBookTemplates.d.ts +2 -2
  103. package/esm/typings/src/pipeline/PipelineInterface/PipelineInterface.d.ts +3 -3
  104. package/esm/typings/src/pipeline/PipelineInterface/constants.d.ts +1 -1
  105. package/esm/typings/src/pipeline/PipelineInterface/getPipelineInterface.d.ts +1 -1
  106. package/esm/typings/src/pipeline/PipelineInterface/isPipelineImplementingInterface.d.ts +5 -4
  107. package/esm/typings/src/pipeline/PipelineInterface/isPipelineInterfacesEqual.d.ts +1 -1
  108. package/esm/typings/src/pipeline/PipelineJson/CommonTaskJson.d.ts +10 -7
  109. package/esm/typings/src/pipeline/PipelineJson/ParameterJson.d.ts +1 -1
  110. package/esm/typings/src/pipeline/PipelineJson/PipelineJson.d.ts +3 -2
  111. package/esm/typings/src/pipeline/PipelineString.d.ts +3 -1
  112. package/esm/typings/src/pipeline/book-notation.d.ts +2 -2
  113. package/esm/typings/src/postprocessing/utils/extractBlock.d.ts +1 -1
  114. package/esm/typings/src/postprocessing/utils/extractJsonBlock.d.ts +2 -2
  115. package/esm/typings/src/prepare/prepareTasks.d.ts +8 -5
  116. package/esm/typings/src/remote-server/openapi.d.ts +1 -1
  117. package/esm/typings/src/remote-server/socket-types/listModels/PromptbookServer_ListModels_Response.d.ts +1 -1
  118. package/esm/typings/src/remote-server/startRemoteServer.d.ts +1 -1
  119. package/esm/typings/src/remote-server/types/RemoteServerOptions.d.ts +7 -6
  120. package/esm/typings/src/scrapers/_boilerplate/BoilerplateScraper.d.ts +3 -3
  121. package/esm/typings/src/scrapers/_boilerplate/createBoilerplateScraper.d.ts +1 -1
  122. package/esm/typings/src/scrapers/_boilerplate/register-metadata.d.ts +1 -1
  123. package/esm/typings/src/scrapers/_common/Converter.d.ts +3 -1
  124. package/esm/typings/src/scrapers/_common/Scraper.d.ts +4 -3
  125. package/esm/typings/src/scrapers/_common/ScraperIntermediateSource.d.ts +4 -2
  126. package/esm/typings/src/scrapers/_common/prepareKnowledgePieces.d.ts +2 -2
  127. package/esm/typings/src/scrapers/_common/register/$provideFilesystemForNode.d.ts +2 -1
  128. package/esm/typings/src/scrapers/_common/register/$provideScrapersForBrowser.d.ts +6 -3
  129. package/esm/typings/src/scrapers/_common/register/$provideScrapersForNode.d.ts +3 -5
  130. package/esm/typings/src/scrapers/_common/register/$scrapersMetadataRegister.d.ts +3 -3
  131. package/esm/typings/src/scrapers/_common/register/$scrapersRegister.d.ts +3 -2
  132. package/esm/typings/src/scrapers/_common/register/ScraperAndConverterMetadata.d.ts +8 -5
  133. package/esm/typings/src/scrapers/_common/register/ScraperConstructor.d.ts +2 -1
  134. package/esm/typings/src/scrapers/_common/utils/getScraperIntermediateSource.d.ts +6 -5
  135. package/esm/typings/src/scrapers/_common/utils/makeKnowledgeSourceHandler.d.ts +3 -1
  136. package/esm/typings/src/scrapers/document/createDocumentScraper.d.ts +1 -1
  137. package/esm/typings/src/scrapers/document-legacy/createLegacyDocumentScraper.d.ts +2 -1
  138. package/esm/typings/src/scrapers/markdown/createMarkdownScraper.d.ts +4 -1
  139. package/esm/typings/src/scrapers/markitdown/MarkitdownScraper.d.ts +1 -1
  140. package/esm/typings/src/scrapers/pdf/createPdfScraper.d.ts +2 -1
  141. package/esm/typings/src/scrapers/website/createWebsiteScraper.d.ts +3 -4
  142. package/esm/typings/src/scripting/javascript/JavascriptExecutionTools.d.ts +1 -1
  143. package/esm/typings/src/scripting/javascript/postprocessing-functions.d.ts +5 -1
  144. package/esm/typings/src/scripting/javascript/utils/preserve.d.ts +1 -1
  145. package/esm/typings/src/storage/_common/PromptbookStorage.d.ts +1 -1
  146. package/esm/typings/src/storage/file-cache-storage/FileCacheStorage.d.ts +12 -5
  147. package/esm/typings/src/storage/file-cache-storage/FileCacheStorageOptions.d.ts +4 -2
  148. package/esm/typings/src/storage/file-cache-storage/utils/nameToSubfolderPath.d.ts +2 -1
  149. package/esm/typings/src/storage/local-storage/getIndexedDbStorage.d.ts +11 -0
  150. package/esm/typings/src/storage/local-storage/utils/IndexedDbStorageOptions.d.ts +14 -0
  151. package/esm/typings/src/storage/local-storage/utils/makePromptbookStorageFromIndexedDb.d.ts +8 -0
  152. package/esm/typings/src/storage/local-storage/utils/makePromptbookStorageFromWebStorage.d.ts +2 -1
  153. package/esm/typings/src/types/IntermediateFilesStrategy.d.ts +2 -1
  154. package/esm/typings/src/types/ModelRequirements.d.ts +2 -2
  155. package/esm/typings/src/types/ModelVariant.d.ts +5 -5
  156. package/esm/typings/src/types/typeAliases.d.ts +22 -19
  157. package/esm/typings/src/utils/$Register.d.ts +8 -7
  158. package/esm/typings/src/utils/editable/edit-pipeline-string/addPipelineCommand.d.ts +2 -2
  159. package/esm/typings/src/utils/editable/edit-pipeline-string/deflatePipeline.d.ts +4 -1
  160. package/esm/typings/src/utils/editable/utils/isFlatPipeline.d.ts +2 -1
  161. package/esm/typings/src/utils/editable/utils/stringifyPipelineJson.d.ts +1 -1
  162. package/esm/typings/src/utils/environment/$getGlobalScope.d.ts +2 -1
  163. package/esm/typings/src/utils/expectation-counters/index.d.ts +1 -1
  164. package/esm/typings/src/utils/markdown/extractAllBlocksFromMarkdown.d.ts +2 -2
  165. package/esm/typings/src/utils/markdown/extractAllListItemsFromMarkdown.d.ts +1 -1
  166. package/esm/typings/src/utils/markdown/extractOneBlockFromMarkdown.d.ts +2 -2
  167. package/esm/typings/src/utils/normalization/nameToUriPart.d.ts +4 -4
  168. package/esm/typings/src/utils/normalization/nameToUriParts.d.ts +4 -4
  169. package/esm/typings/src/utils/normalization/normalize-to-kebab-case.d.ts +3 -3
  170. package/esm/typings/src/utils/normalization/normalizeTo_SCREAMING_CASE.d.ts +3 -3
  171. package/esm/typings/src/utils/normalization/normalizeTo_camelCase.d.ts +4 -4
  172. package/esm/typings/src/utils/normalization/normalizeTo_snake_case.d.ts +3 -3
  173. package/esm/typings/src/utils/normalization/removeDiacritics.d.ts +3 -3
  174. package/esm/typings/src/utils/normalization/searchKeywords.d.ts +4 -1
  175. package/esm/typings/src/utils/normalization/titleToName.d.ts +4 -4
  176. package/esm/typings/src/utils/organization/TODO_USE.d.ts +1 -1
  177. package/esm/typings/src/utils/organization/empty_object.d.ts +2 -2
  178. package/esm/typings/src/utils/organization/just.d.ts +1 -1
  179. package/esm/typings/src/utils/organization/just_empty_object.d.ts +4 -4
  180. package/esm/typings/src/utils/organization/keepUnused.d.ts +1 -1
  181. package/esm/typings/src/utils/parameters/mapAvailableToExpectedParameters.d.ts +7 -7
  182. package/esm/typings/src/utils/removeQuotes.d.ts +2 -2
  183. package/esm/typings/src/utils/serialization/clonePipeline.d.ts +4 -3
  184. package/esm/typings/src/utils/serialization/deepClone.d.ts +5 -1
  185. package/esm/typings/src/utils/trimCodeBlock.d.ts +1 -1
  186. package/esm/typings/src/utils/trimEndOfCodeBlock.d.ts +1 -1
  187. package/esm/typings/src/utils/unwrapResult.d.ts +2 -2
  188. package/esm/typings/src/utils/validators/javascriptName/isValidJavascriptName.d.ts +3 -3
  189. package/esm/typings/src/utils/validators/parameterName/validateParameterName.d.ts +5 -4
  190. package/esm/typings/src/utils/validators/semanticVersion/isValidPromptbookVersion.d.ts +1 -1
  191. package/esm/typings/src/utils/validators/semanticVersion/isValidSemanticVersion.d.ts +1 -1
  192. package/esm/typings/src/utils/validators/url/isHostnameOnPrivateNetwork.d.ts +1 -1
  193. package/esm/typings/src/utils/validators/url/isUrlOnPrivateNetwork.d.ts +1 -1
  194. package/esm/typings/src/utils/validators/url/isValidPipelineUrl.d.ts +1 -1
  195. package/esm/typings/src/utils/validators/url/isValidUrl.d.ts +1 -1
  196. package/esm/typings/src/version.d.ts +2 -1
  197. package/esm/typings/src/wizzard/wizzard.d.ts +1 -1
  198. package/package.json +14 -2
  199. package/umd/index.umd.js +522 -514
  200. package/umd/index.umd.js.map +1 -1
  201. package/esm/typings/src/formats/_common/FormatSubvalueDefinition.d.ts +0 -31
  202. package/esm/typings/src/formats/csv/CsvFormatDefinition.d.ts +0 -17
  203. package/esm/typings/src/formats/json/JsonFormatDefinition.d.ts +0 -19
  204. package/esm/typings/src/formats/xml/XmlFormatDefinition.d.ts +0 -19
  205. /package/esm/typings/src/llm-providers/{multiple → _multiple}/MultipleLlmExecutionTools.d.ts +0 -0
  206. /package/esm/typings/src/llm-providers/{multiple → _multiple}/joinLlmExecutionTools.d.ts +0 -0
  207. /package/esm/typings/src/llm-providers/{multiple → _multiple}/playground/playground.d.ts +0 -0
package/esm/index.es.js CHANGED
@@ -19,7 +19,7 @@ const BOOK_LANGUAGE_VERSION = '1.0.0';
19
19
  * @generated
20
20
  * @see https://github.com/webgptorg/promptbook
21
21
  */
22
- const PROMPTBOOK_ENGINE_VERSION = '0.92.0-8';
22
+ const PROMPTBOOK_ENGINE_VERSION = '0.92.0';
23
23
  /**
24
24
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
25
25
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -75,7 +75,7 @@ const VALUE_STRINGS = {
75
75
  const SMALL_NUMBER = 0.001;
76
76
  // <- TODO: [🧜‍♂️]
77
77
  /**
78
- * @@@
78
+ * Default settings for parsing and generating CSV files in Promptbook.
79
79
  *
80
80
  * @public exported from `@promptbook/core`
81
81
  */
@@ -90,6 +90,48 @@ Object.freeze({
90
90
  * TODO: [🧠][🧜‍♂️] Maybe join remoteServerUrl and path into single value
91
91
  */
92
92
 
93
+ /**
94
+ * Orders JSON object by keys
95
+ *
96
+ * @returns The same type of object as the input re-ordered
97
+ * @public exported from `@promptbook/utils`
98
+ */
99
+ function orderJson(options) {
100
+ const { value, order } = options;
101
+ const orderedValue = {
102
+ ...(order === undefined ? {} : Object.fromEntries(order.map((key) => [key, undefined]))),
103
+ ...value,
104
+ };
105
+ return orderedValue;
106
+ }
107
+
108
+ /**
109
+ * Freezes the given object and all its nested objects recursively
110
+ *
111
+ * Note: `$` is used to indicate that this function is not a pure function - it mutates given object
112
+ * Note: This function mutates the object and returns the original (but mutated-deep-freezed) object
113
+ *
114
+ * @returns The same object as the input, but deeply frozen
115
+ * @public exported from `@promptbook/utils`
116
+ */
117
+ function $deepFreeze(objectValue) {
118
+ if (Array.isArray(objectValue)) {
119
+ return Object.freeze(objectValue.map((item) => $deepFreeze(item)));
120
+ }
121
+ const propertyNames = Object.getOwnPropertyNames(objectValue);
122
+ for (const propertyName of propertyNames) {
123
+ const value = objectValue[propertyName];
124
+ if (value && typeof value === 'object') {
125
+ $deepFreeze(value);
126
+ }
127
+ }
128
+ Object.freeze(objectValue);
129
+ return objectValue;
130
+ }
131
+ /**
132
+ * TODO: [🧠] Is there a way how to meaningfully test this utility
133
+ */
134
+
93
135
  /**
94
136
  * Make error report URL for the given error
95
137
  *
@@ -145,7 +187,7 @@ class UnexpectedError extends Error {
145
187
  ${block(message)}
146
188
 
147
189
  Note: This error should not happen.
148
- It's probbably a bug in the pipeline collection
190
+ It's probably a bug in the pipeline collection
149
191
 
150
192
  Please report issue:
151
193
  ${block(getErrorReportUrl(new Error(message)).href)}
@@ -159,70 +201,341 @@ class UnexpectedError extends Error {
159
201
  }
160
202
 
161
203
  /**
162
- * @@@
204
+ * This error type indicates that somewhere in the code non-Error object was thrown and it was wrapped into the `WrappedError`
163
205
  *
164
- * @param text @@@
165
- * @param _isFirstLetterCapital @@@
166
- * @returns @@@
167
- * @example 'helloWorld'
168
- * @example 'iLovePromptbook'
206
+ * @public exported from `@promptbook/core`
207
+ */
208
+ class WrappedError extends Error {
209
+ constructor(whatWasThrown) {
210
+ const tag = `[🤮]`;
211
+ console.error(tag, whatWasThrown);
212
+ super(spaceTrim$1(`
213
+ Non-Error object was thrown
214
+
215
+ Note: Look for ${tag} in the console for more details
216
+ Please report issue on ${ADMIN_EMAIL}
217
+ `));
218
+ this.name = 'WrappedError';
219
+ Object.setPrototypeOf(this, WrappedError.prototype);
220
+ }
221
+ }
222
+
223
+ /**
224
+ * Helper used in catch blocks to assert that the error is an instance of `Error`
225
+ *
226
+ * @param whatWasThrown Any object that was thrown
227
+ * @returns Nothing if the error is an instance of `Error`
228
+ * @throws `WrappedError` or `UnexpectedError` if the error is not standard
229
+ *
230
+ * @private within the repository
231
+ */
232
+ function assertsError(whatWasThrown) {
233
+ // Case 1: Handle error which was rethrown as `WrappedError`
234
+ if (whatWasThrown instanceof WrappedError) {
235
+ const wrappedError = whatWasThrown;
236
+ throw wrappedError;
237
+ }
238
+ // Case 2: Handle unexpected errors
239
+ if (whatWasThrown instanceof UnexpectedError) {
240
+ const unexpectedError = whatWasThrown;
241
+ throw unexpectedError;
242
+ }
243
+ // Case 3: Handle standard errors - keep them up to consumer
244
+ if (whatWasThrown instanceof Error) {
245
+ return;
246
+ }
247
+ // Case 4: Handle non-standard errors - wrap them into `WrappedError` and throw
248
+ throw new WrappedError(whatWasThrown);
249
+ }
250
+
251
+ /**
252
+ * Checks if the value is [🚉] serializable as JSON
253
+ * If not, throws an UnexpectedError with a rich error message and tracking
254
+ *
255
+ * - Almost all primitives are serializable BUT:
256
+ * - `undefined` is not serializable
257
+ * - `NaN` is not serializable
258
+ * - Objects and arrays are serializable if all their properties are serializable
259
+ * - Functions are not serializable
260
+ * - Circular references are not serializable
261
+ * - `Date` objects are not serializable
262
+ * - `Map` and `Set` objects are not serializable
263
+ * - `RegExp` objects are not serializable
264
+ * - `Error` objects are not serializable
265
+ * - `Symbol` objects are not serializable
266
+ * - And much more...
267
+ *
268
+ * @throws UnexpectedError if the value is not serializable as JSON
169
269
  * @public exported from `@promptbook/utils`
170
270
  */
171
- function normalizeTo_camelCase(text, _isFirstLetterCapital = false) {
172
- let charType;
173
- let lastCharType = null;
174
- let normalizedName = '';
175
- for (const char of text) {
176
- let normalizedChar;
177
- if (/^[a-z]$/.test(char)) {
178
- charType = 'LOWERCASE';
179
- normalizedChar = char;
271
+ function checkSerializableAsJson(options) {
272
+ const { value, name, message } = options;
273
+ if (value === undefined) {
274
+ throw new UnexpectedError(`${name} is undefined`);
275
+ }
276
+ else if (value === null) {
277
+ return;
278
+ }
279
+ else if (typeof value === 'boolean') {
280
+ return;
281
+ }
282
+ else if (typeof value === 'number' && !isNaN(value)) {
283
+ return;
284
+ }
285
+ else if (typeof value === 'string') {
286
+ return;
287
+ }
288
+ else if (typeof value === 'symbol') {
289
+ throw new UnexpectedError(`${name} is symbol`);
290
+ }
291
+ else if (typeof value === 'function') {
292
+ throw new UnexpectedError(`${name} is function`);
293
+ }
294
+ else if (typeof value === 'object' && Array.isArray(value)) {
295
+ for (let i = 0; i < value.length; i++) {
296
+ checkSerializableAsJson({ name: `${name}[${i}]`, value: value[i], message });
180
297
  }
181
- else if (/^[A-Z]$/.test(char)) {
182
- charType = 'UPPERCASE';
183
- normalizedChar = char.toLowerCase();
298
+ }
299
+ else if (typeof value === 'object') {
300
+ if (value instanceof Date) {
301
+ throw new UnexpectedError(spaceTrim((block) => `
302
+ \`${name}\` is Date
303
+
304
+ Use \`string_date_iso8601\` instead
305
+
306
+ Additional message for \`${name}\`:
307
+ ${block(message || '(nothing)')}
308
+ `));
184
309
  }
185
- else if (/^[0-9]$/.test(char)) {
186
- charType = 'NUMBER';
187
- normalizedChar = char;
310
+ else if (value instanceof Map) {
311
+ throw new UnexpectedError(`${name} is Map`);
188
312
  }
189
- else {
190
- charType = 'OTHER';
191
- normalizedChar = '';
313
+ else if (value instanceof Set) {
314
+ throw new UnexpectedError(`${name} is Set`);
192
315
  }
193
- if (!lastCharType) {
194
- if (_isFirstLetterCapital) {
195
- normalizedChar = normalizedChar.toUpperCase(); //TODO: DRY
196
- }
316
+ else if (value instanceof RegExp) {
317
+ throw new UnexpectedError(`${name} is RegExp`);
197
318
  }
198
- else if (charType !== lastCharType &&
199
- !(charType === 'LOWERCASE' && lastCharType === 'UPPERCASE') &&
200
- !(lastCharType === 'NUMBER') &&
201
- !(charType === 'NUMBER')) {
202
- normalizedChar = normalizedChar.toUpperCase(); //TODO: [🌺] DRY
319
+ else if (value instanceof Error) {
320
+ throw new UnexpectedError(spaceTrim((block) => `
321
+ \`${name}\` is unserialized Error
322
+
323
+ Use function \`serializeError\`
324
+
325
+ Additional message for \`${name}\`:
326
+ ${block(message || '(nothing)')}
327
+
328
+ `));
329
+ }
330
+ else {
331
+ for (const [subName, subValue] of Object.entries(value)) {
332
+ if (subValue === undefined) {
333
+ // Note: undefined in object is serializable - it is just omited
334
+ continue;
335
+ }
336
+ checkSerializableAsJson({ name: `${name}.${subName}`, value: subValue, message });
337
+ }
338
+ try {
339
+ JSON.stringify(value); // <- TODO: [0]
340
+ }
341
+ catch (error) {
342
+ assertsError(error);
343
+ throw new UnexpectedError(spaceTrim((block) => `
344
+ \`${name}\` is not serializable
345
+
346
+ ${block(error.stack || error.message)}
347
+
348
+ Additional message for \`${name}\`:
349
+ ${block(message || '(nothing)')}
350
+ `));
351
+ }
352
+ /*
353
+ TODO: [0] Is there some more elegant way to check circular references?
354
+ const seen = new Set();
355
+ const stack = [{ value }];
356
+ while (stack.length > 0) {
357
+ const { value } = stack.pop()!;
358
+ if (typeof value === 'object' && value !== null) {
359
+ if (seen.has(value)) {
360
+ throw new UnexpectedError(`${name} has circular reference`);
361
+ }
362
+ seen.add(value);
363
+ if (Array.isArray(value)) {
364
+ stack.push(...value.map((value) => ({ value })));
365
+ } else {
366
+ stack.push(...Object.values(value).map((value) => ({ value })));
367
+ }
368
+ }
369
+ }
370
+ */
371
+ return;
203
372
  }
204
- normalizedName += normalizedChar;
205
- lastCharType = charType;
206
373
  }
207
- return normalizedName;
374
+ else {
375
+ throw new UnexpectedError(spaceTrim((block) => `
376
+ \`${name}\` is unknown type
377
+
378
+ Additional message for \`${name}\`:
379
+ ${block(message || '(nothing)')}
380
+ `));
381
+ }
208
382
  }
209
383
  /**
210
- * TODO: [🌺] Use some intermediate util splitWords
384
+ * TODO: Can be return type more type-safe? like `asserts options.value is JsonValue`
385
+ * TODO: [🧠][main] !!3 In-memory cache of same values to prevent multiple checks
386
+ * Note: [🐠] This is how `checkSerializableAsJson` + `isSerializableAsJson` together can just retun true/false or rich error message
211
387
  */
212
388
 
213
389
  /**
214
- * Removes emojis from a string and fix whitespaces
390
+ * Creates a deep clone of the given object
215
391
  *
216
- * @param text with emojis
217
- * @returns text without emojis
392
+ * Note: This method only works for objects that are fully serializable to JSON and do not contain functions, Dates, or special types.
393
+ *
394
+ * @param objectValue The object to clone.
395
+ * @returns A deep, writable clone of the input object.
218
396
  * @public exported from `@promptbook/utils`
219
397
  */
220
- function removeEmojis(text) {
221
- // Replace emojis (and also ZWJ sequence) with hyphens
222
- text = text.replace(/(\p{Extended_Pictographic})\p{Modifier_Symbol}/gu, '$1');
223
- text = text.replace(/(\p{Extended_Pictographic})[\u{FE00}-\u{FE0F}]/gu, '$1');
224
- text = text.replace(/(\p{Extended_Pictographic})(\u{200D}\p{Extended_Pictographic})*/gu, '$1');
225
- text = text.replace(/\p{Extended_Pictographic}/gu, '');
398
+ function deepClone(objectValue) {
399
+ return JSON.parse(JSON.stringify(objectValue));
400
+ /*
401
+ TODO: [🧠] Is there a better implementation?
402
+ > const propertyNames = Object.getOwnPropertyNames(objectValue);
403
+ > for (const propertyName of propertyNames) {
404
+ > const value = (objectValue as really_any)[propertyName];
405
+ > if (value && typeof value === 'object') {
406
+ > deepClone(value);
407
+ > }
408
+ > }
409
+ > return Object.assign({}, objectValue);
410
+ */
411
+ }
412
+ /**
413
+ * TODO: [🧠] Is there a way how to meaningfully test this utility
414
+ */
415
+
416
+ /**
417
+ * Utility to export a JSON object from a function
418
+ *
419
+ * 1) Checks if the value is serializable as JSON
420
+ * 2) Makes a deep clone of the object
421
+ * 2) Orders the object properties
422
+ * 2) Deeply freezes the cloned object
423
+ *
424
+ * Note: This function does not mutates the given object
425
+ *
426
+ * @returns The same type of object as the input but read-only and re-ordered
427
+ * @public exported from `@promptbook/utils`
428
+ */
429
+ function exportJson(options) {
430
+ const { name, value, order, message } = options;
431
+ checkSerializableAsJson({ name, value, message });
432
+ const orderedValue =
433
+ // TODO: Fix error "Type instantiation is excessively deep and possibly infinite."
434
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
435
+ // @ts-ignore
436
+ order === undefined
437
+ ? deepClone(value)
438
+ : orderJson({
439
+ value: value,
440
+ // <- Note: checkSerializableAsJson asserts that the value is serializable as JSON
441
+ order: order,
442
+ });
443
+ $deepFreeze(orderedValue);
444
+ return orderedValue;
445
+ }
446
+ /**
447
+ * TODO: [🧠] Is there a way how to meaningfully test this utility
448
+ */
449
+
450
+ /**
451
+ * The names of the parameters that are reserved for special purposes
452
+ *
453
+ * @public exported from `@promptbook/core`
454
+ */
455
+ exportJson({
456
+ name: 'RESERVED_PARAMETER_NAMES',
457
+ message: `The names of the parameters that are reserved for special purposes`,
458
+ value: [
459
+ 'content',
460
+ 'context',
461
+ 'knowledge',
462
+ 'examples',
463
+ 'modelName',
464
+ 'currentDate',
465
+ // <- TODO: list here all command names
466
+ // <- TODO: Add more like 'date', 'modelName',...
467
+ // <- TODO: Add [emoji] + instructions ACRY when adding new reserved parameter
468
+ ],
469
+ });
470
+ /**
471
+ * Note: [💞] Ignore a discrepancy between file name and entity name
472
+ */
473
+
474
+ /**
475
+ * Normalizes a given text to camelCase format.
476
+ *
477
+ * @param text The text to be normalized.
478
+ * @param _isFirstLetterCapital Whether the first letter should be capitalized.
479
+ * @returns The camelCase formatted string.
480
+ * @example 'helloWorld'
481
+ * @example 'iLovePromptbook'
482
+ * @public exported from `@promptbook/utils`
483
+ */
484
+ function normalizeTo_camelCase(text, _isFirstLetterCapital = false) {
485
+ let charType;
486
+ let lastCharType = null;
487
+ let normalizedName = '';
488
+ for (const char of text) {
489
+ let normalizedChar;
490
+ if (/^[a-z]$/.test(char)) {
491
+ charType = 'LOWERCASE';
492
+ normalizedChar = char;
493
+ }
494
+ else if (/^[A-Z]$/.test(char)) {
495
+ charType = 'UPPERCASE';
496
+ normalizedChar = char.toLowerCase();
497
+ }
498
+ else if (/^[0-9]$/.test(char)) {
499
+ charType = 'NUMBER';
500
+ normalizedChar = char;
501
+ }
502
+ else {
503
+ charType = 'OTHER';
504
+ normalizedChar = '';
505
+ }
506
+ if (!lastCharType) {
507
+ if (_isFirstLetterCapital) {
508
+ normalizedChar = normalizedChar.toUpperCase(); //TODO: DRY
509
+ }
510
+ }
511
+ else if (charType !== lastCharType &&
512
+ !(charType === 'LOWERCASE' && lastCharType === 'UPPERCASE') &&
513
+ !(lastCharType === 'NUMBER') &&
514
+ !(charType === 'NUMBER')) {
515
+ normalizedChar = normalizedChar.toUpperCase(); //TODO: [🌺] DRY
516
+ }
517
+ normalizedName += normalizedChar;
518
+ lastCharType = charType;
519
+ }
520
+ return normalizedName;
521
+ }
522
+ /**
523
+ * TODO: [🌺] Use some intermediate util splitWords
524
+ */
525
+
526
+ /**
527
+ * Removes emojis from a string and fix whitespaces
528
+ *
529
+ * @param text with emojis
530
+ * @returns text without emojis
531
+ * @public exported from `@promptbook/utils`
532
+ */
533
+ function removeEmojis(text) {
534
+ // Replace emojis (and also ZWJ sequence) with hyphens
535
+ text = text.replace(/(\p{Extended_Pictographic})\p{Modifier_Symbol}/gu, '$1');
536
+ text = text.replace(/(\p{Extended_Pictographic})[\u{FE00}-\u{FE0F}]/gu, '$1');
537
+ text = text.replace(/(\p{Extended_Pictographic})(\u{200D}\p{Extended_Pictographic})*/gu, '$1');
538
+ text = text.replace(/\p{Extended_Pictographic}/gu, '');
226
539
  return text;
227
540
  }
228
541
 
@@ -453,472 +766,163 @@ for (let i = 0; i < defaultDiacriticsRemovalMap.length; i++) {
453
766
  for (let j = 0; j < letters.length; j++) {
454
767
  DIACRITIC_VARIANTS_LETTERS[letters[j]] = defaultDiacriticsRemovalMap[i].base;
455
768
  }
456
- }
457
- // <- TODO: [🍓] Put to maker function to save execution time if not needed
458
- /*
459
- @see https://stackoverflow.com/questions/990904/remove-accents-diacritics-in-a-string-in-javascript
460
- Licensed under the Apache License, Version 2.0 (the "License");
461
- you may not use this file except in compliance with the License.
462
- You may obtain a copy of the License at
463
-
464
- http://www.apache.org/licenses/LICENSE-2.0
465
-
466
- Unless required by applicable law or agreed to in writing, software
467
- distributed under the License is distributed on an "AS IS" BASIS,
468
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
469
- See the License for the specific language governing permissions and
470
- limitations under the License.
471
- */
472
-
473
- /**
474
- * @@@
475
- *
476
- * @param input @@@
477
- * @returns @@@
478
- * @public exported from `@promptbook/utils`
479
- */
480
- function removeDiacritics(input) {
481
- /*eslint no-control-regex: "off"*/
482
- return input.replace(/[^\u0000-\u007E]/g, (a) => {
483
- return DIACRITIC_VARIANTS_LETTERS[a] || a;
484
- });
485
- }
486
- /**
487
- * TODO: [Ж] Variant for cyrillic (and in general non-latin) letters
488
- */
489
-
490
- /**
491
- * @@@
492
- *
493
- * @param text @@@
494
- * @returns @@@
495
- * @example 'hello-world'
496
- * @example 'i-love-promptbook'
497
- * @public exported from `@promptbook/utils`
498
- */
499
- function normalizeToKebabCase(text) {
500
- text = removeDiacritics(text);
501
- let charType;
502
- let lastCharType = 'OTHER';
503
- let normalizedName = '';
504
- for (const char of text) {
505
- let normalizedChar;
506
- if (/^[a-z]$/.test(char)) {
507
- charType = 'LOWERCASE';
508
- normalizedChar = char;
509
- }
510
- else if (/^[A-Z]$/.test(char)) {
511
- charType = 'UPPERCASE';
512
- normalizedChar = char.toLowerCase();
513
- }
514
- else if (/^[0-9]$/.test(char)) {
515
- charType = 'NUMBER';
516
- normalizedChar = char;
517
- }
518
- else {
519
- charType = 'OTHER';
520
- normalizedChar = '-';
521
- }
522
- if (charType !== lastCharType &&
523
- !(lastCharType === 'UPPERCASE' && charType === 'LOWERCASE') &&
524
- !(lastCharType === 'NUMBER') &&
525
- !(charType === 'NUMBER')) {
526
- normalizedName += '-';
527
- }
528
- normalizedName += normalizedChar;
529
- lastCharType = charType;
530
- }
531
- normalizedName = normalizedName.split(/-+/g).join('-');
532
- normalizedName = normalizedName.split(/-?\/-?/g).join('/');
533
- normalizedName = normalizedName.replace(/^-/, '');
534
- normalizedName = normalizedName.replace(/-$/, '');
535
- return normalizedName;
536
- }
537
- /**
538
- * Note: [💞] Ignore a discrepancy between file name and entity name
539
- */
540
-
541
- /**
542
- * This error indicates that the promptbook in a markdown format cannot be parsed into a valid promptbook object
543
- *
544
- * @public exported from `@promptbook/core`
545
- */
546
- class ParseError extends Error {
547
- constructor(message) {
548
- super(message);
549
- this.name = 'ParseError';
550
- Object.setPrototypeOf(this, ParseError.prototype);
551
- }
552
- }
553
- /**
554
- * TODO: Maybe split `ParseError` and `ApplyError`
555
- */
556
-
557
- /**
558
- * Generates random token
559
- *
560
- * Note: This function is cryptographically secure (it uses crypto.randomBytes internally)
561
- *
562
- * @private internal helper function
563
- * @returns secure random token
564
- */
565
- function $randomToken(randomness) {
566
- return randomBytes(randomness).toString('hex');
567
- }
568
- /**
569
- * TODO: Maybe use nanoid instead https://github.com/ai/nanoid
570
- */
571
-
572
- /**
573
- * This error indicates errors during the execution of the pipeline
574
- *
575
- * @public exported from `@promptbook/core`
576
- */
577
- class PipelineExecutionError extends Error {
578
- constructor(message) {
579
- // Added id parameter
580
- super(message);
581
- this.name = 'PipelineExecutionError';
582
- // TODO: [🐙] DRY - Maybe $randomId
583
- this.id = `error-${$randomToken(8 /* <- TODO: To global config + Use Base58 to avoid simmilar char conflicts */)}`;
584
- Object.setPrototypeOf(this, PipelineExecutionError.prototype);
585
- }
586
- }
587
- /**
588
- * TODO: [🧠][🌂] Add id to all errors
589
- */
590
-
591
- /**
592
- * This error type indicates that somewhere in the code non-Error object was thrown and it was wrapped into the `WrappedError`
593
- *
594
- * @public exported from `@promptbook/core`
595
- */
596
- class WrappedError extends Error {
597
- constructor(whatWasThrown) {
598
- const tag = `[🤮]`;
599
- console.error(tag, whatWasThrown);
600
- super(spaceTrim$1(`
601
- Non-Error object was thrown
602
-
603
- Note: Look for ${tag} in the console for more details
604
- Please report issue on ${ADMIN_EMAIL}
605
- `));
606
- this.name = 'WrappedError';
607
- Object.setPrototypeOf(this, WrappedError.prototype);
608
- }
609
- }
610
-
611
- /**
612
- * Index of all javascript errors
613
- *
614
- * @private for internal usage
615
- */
616
- ({
617
- Error,
618
- EvalError,
619
- RangeError,
620
- ReferenceError,
621
- SyntaxError,
622
- TypeError,
623
- URIError,
624
- AggregateError,
625
- /*
626
- Note: Not widely supported
627
- > InternalError,
628
- > ModuleError,
629
- > HeapError,
630
- > WebAssemblyCompileError,
631
- > WebAssemblyRuntimeError,
632
- */
633
- });
634
- /**
635
- * Note: [💞] Ignore a discrepancy between file name and entity name
636
- */
637
-
638
- /**
639
- * Helper used in catch blocks to assert that the error is an instance of `Error`
640
- *
641
- * @param whatWasThrown Any object that was thrown
642
- * @returns Nothing if the error is an instance of `Error`
643
- * @throws `WrappedError` or `UnexpectedError` if the error is not standard
644
- *
645
- * @private within the repository
646
- */
647
- function assertsError(whatWasThrown) {
648
- // Case 1: Handle error which was rethrown as `WrappedError`
649
- if (whatWasThrown instanceof WrappedError) {
650
- const wrappedError = whatWasThrown;
651
- throw wrappedError;
652
- }
653
- // Case 2: Handle unexpected errors
654
- if (whatWasThrown instanceof UnexpectedError) {
655
- const unexpectedError = whatWasThrown;
656
- throw unexpectedError;
657
- }
658
- // Case 3: Handle standard errors - keep them up to consumer
659
- if (whatWasThrown instanceof Error) {
660
- return;
661
- }
662
- // Case 4: Handle non-standard errors - wrap them into `WrappedError` and throw
663
- throw new WrappedError(whatWasThrown);
664
- }
665
-
666
- /**
667
- * Orders JSON object by keys
668
- *
669
- * @returns The same type of object as the input re-ordered
670
- * @public exported from `@promptbook/utils`
671
- */
672
- function orderJson(options) {
673
- const { value, order } = options;
674
- const orderedValue = {
675
- ...(order === undefined ? {} : Object.fromEntries(order.map((key) => [key, undefined]))),
676
- ...value,
677
- };
678
- return orderedValue;
679
- }
680
-
681
- /**
682
- * Freezes the given object and all its nested objects recursively
683
- *
684
- * Note: `$` is used to indicate that this function is not a pure function - it mutates given object
685
- * Note: This function mutates the object and returns the original (but mutated-deep-freezed) object
686
- *
687
- * @returns The same object as the input, but deeply frozen
688
- * @public exported from `@promptbook/utils`
689
- */
690
- function $deepFreeze(objectValue) {
691
- if (Array.isArray(objectValue)) {
692
- return Object.freeze(objectValue.map((item) => $deepFreeze(item)));
693
- }
694
- const propertyNames = Object.getOwnPropertyNames(objectValue);
695
- for (const propertyName of propertyNames) {
696
- const value = objectValue[propertyName];
697
- if (value && typeof value === 'object') {
698
- $deepFreeze(value);
699
- }
700
- }
701
- Object.freeze(objectValue);
702
- return objectValue;
703
- }
704
- /**
705
- * TODO: [🧠] Is there a way how to meaningfully test this utility
706
- */
707
-
708
- /**
709
- * Checks if the value is [🚉] serializable as JSON
710
- * If not, throws an UnexpectedError with a rich error message and tracking
711
- *
712
- * - Almost all primitives are serializable BUT:
713
- * - `undefined` is not serializable
714
- * - `NaN` is not serializable
715
- * - Objects and arrays are serializable if all their properties are serializable
716
- * - Functions are not serializable
717
- * - Circular references are not serializable
718
- * - `Date` objects are not serializable
719
- * - `Map` and `Set` objects are not serializable
720
- * - `RegExp` objects are not serializable
721
- * - `Error` objects are not serializable
722
- * - `Symbol` objects are not serializable
723
- * - And much more...
724
- *
725
- * @throws UnexpectedError if the value is not serializable as JSON
726
- * @public exported from `@promptbook/utils`
727
- */
728
- function checkSerializableAsJson(options) {
729
- const { value, name, message } = options;
730
- if (value === undefined) {
731
- throw new UnexpectedError(`${name} is undefined`);
732
- }
733
- else if (value === null) {
734
- return;
735
- }
736
- else if (typeof value === 'boolean') {
737
- return;
738
- }
739
- else if (typeof value === 'number' && !isNaN(value)) {
740
- return;
741
- }
742
- else if (typeof value === 'string') {
743
- return;
744
- }
745
- else if (typeof value === 'symbol') {
746
- throw new UnexpectedError(`${name} is symbol`);
747
- }
748
- else if (typeof value === 'function') {
749
- throw new UnexpectedError(`${name} is function`);
750
- }
751
- else if (typeof value === 'object' && Array.isArray(value)) {
752
- for (let i = 0; i < value.length; i++) {
753
- checkSerializableAsJson({ name: `${name}[${i}]`, value: value[i], message });
754
- }
755
- }
756
- else if (typeof value === 'object') {
757
- if (value instanceof Date) {
758
- throw new UnexpectedError(spaceTrim((block) => `
759
- \`${name}\` is Date
760
-
761
- Use \`string_date_iso8601\` instead
769
+ }
770
+ // <- TODO: [🍓] Put to maker function to save execution time if not needed
771
+ /*
772
+ @see https://stackoverflow.com/questions/990904/remove-accents-diacritics-in-a-string-in-javascript
773
+ Licensed under the Apache License, Version 2.0 (the "License");
774
+ you may not use this file except in compliance with the License.
775
+ You may obtain a copy of the License at
762
776
 
763
- Additional message for \`${name}\`:
764
- ${block(message || '(nothing)')}
765
- `));
766
- }
767
- else if (value instanceof Map) {
768
- throw new UnexpectedError(`${name} is Map`);
769
- }
770
- else if (value instanceof Set) {
771
- throw new UnexpectedError(`${name} is Set`);
772
- }
773
- else if (value instanceof RegExp) {
774
- throw new UnexpectedError(`${name} is RegExp`);
775
- }
776
- else if (value instanceof Error) {
777
- throw new UnexpectedError(spaceTrim((block) => `
778
- \`${name}\` is unserialized Error
777
+ http://www.apache.org/licenses/LICENSE-2.0
779
778
 
780
- Use function \`serializeError\`
779
+ Unless required by applicable law or agreed to in writing, software
780
+ distributed under the License is distributed on an "AS IS" BASIS,
781
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
782
+ See the License for the specific language governing permissions and
783
+ limitations under the License.
784
+ */
781
785
 
782
- Additional message for \`${name}\`:
783
- ${block(message || '(nothing)')}
786
+ /**
787
+ * Removes diacritic marks (accents) from characters in a string.
788
+ *
789
+ * @param input The string containing diacritics to be normalized.
790
+ * @returns The string with diacritics removed or normalized.
791
+ * @public exported from `@promptbook/utils`
792
+ */
793
+ function removeDiacritics(input) {
794
+ /*eslint no-control-regex: "off"*/
795
+ return input.replace(/[^\u0000-\u007E]/g, (a) => {
796
+ return DIACRITIC_VARIANTS_LETTERS[a] || a;
797
+ });
798
+ }
799
+ /**
800
+ * TODO: [Ж] Variant for cyrillic (and in general non-latin) letters
801
+ */
784
802
 
785
- `));
803
+ /**
804
+ * Converts a given text to kebab-case format.
805
+ *
806
+ * @param text The text to be converted.
807
+ * @returns The kebab-case formatted string.
808
+ * @example 'hello-world'
809
+ * @example 'i-love-promptbook'
810
+ * @public exported from `@promptbook/utils`
811
+ */
812
+ function normalizeToKebabCase(text) {
813
+ text = removeDiacritics(text);
814
+ let charType;
815
+ let lastCharType = 'OTHER';
816
+ let normalizedName = '';
817
+ for (const char of text) {
818
+ let normalizedChar;
819
+ if (/^[a-z]$/.test(char)) {
820
+ charType = 'LOWERCASE';
821
+ normalizedChar = char;
822
+ }
823
+ else if (/^[A-Z]$/.test(char)) {
824
+ charType = 'UPPERCASE';
825
+ normalizedChar = char.toLowerCase();
826
+ }
827
+ else if (/^[0-9]$/.test(char)) {
828
+ charType = 'NUMBER';
829
+ normalizedChar = char;
786
830
  }
787
831
  else {
788
- for (const [subName, subValue] of Object.entries(value)) {
789
- if (subValue === undefined) {
790
- // Note: undefined in object is serializable - it is just omited
791
- continue;
792
- }
793
- checkSerializableAsJson({ name: `${name}.${subName}`, value: subValue, message });
794
- }
795
- try {
796
- JSON.stringify(value); // <- TODO: [0]
797
- }
798
- catch (error) {
799
- assertsError(error);
800
- throw new UnexpectedError(spaceTrim((block) => `
801
- \`${name}\` is not serializable
802
-
803
- ${block(error.stack || error.message)}
804
-
805
- Additional message for \`${name}\`:
806
- ${block(message || '(nothing)')}
807
- `));
808
- }
809
- /*
810
- TODO: [0] Is there some more elegant way to check circular references?
811
- const seen = new Set();
812
- const stack = [{ value }];
813
- while (stack.length > 0) {
814
- const { value } = stack.pop()!;
815
- if (typeof value === 'object' && value !== null) {
816
- if (seen.has(value)) {
817
- throw new UnexpectedError(`${name} has circular reference`);
818
- }
819
- seen.add(value);
820
- if (Array.isArray(value)) {
821
- stack.push(...value.map((value) => ({ value })));
822
- } else {
823
- stack.push(...Object.values(value).map((value) => ({ value })));
824
- }
825
- }
826
- }
827
- */
828
- return;
832
+ charType = 'OTHER';
833
+ normalizedChar = '-';
829
834
  }
835
+ if (charType !== lastCharType &&
836
+ !(lastCharType === 'UPPERCASE' && charType === 'LOWERCASE') &&
837
+ !(lastCharType === 'NUMBER') &&
838
+ !(charType === 'NUMBER')) {
839
+ normalizedName += '-';
840
+ }
841
+ normalizedName += normalizedChar;
842
+ lastCharType = charType;
830
843
  }
831
- else {
832
- throw new UnexpectedError(spaceTrim((block) => `
833
- \`${name}\` is unknown type
834
-
835
- Additional message for \`${name}\`:
836
- ${block(message || '(nothing)')}
837
- `));
838
- }
844
+ normalizedName = normalizedName.split(/-+/g).join('-');
845
+ normalizedName = normalizedName.split(/-?\/-?/g).join('/');
846
+ normalizedName = normalizedName.replace(/^-/, '');
847
+ normalizedName = normalizedName.replace(/-$/, '');
848
+ return normalizedName;
839
849
  }
840
850
  /**
841
- * TODO: Can be return type more type-safe? like `asserts options.value is JsonValue`
842
- * TODO: [🧠][main] !!3 In-memory cache of same values to prevent multiple checks
843
- * Note: [🐠] This is how `checkSerializableAsJson` + `isSerializableAsJson` together can just retun true/false or rich error message
851
+ * Note: [💞] Ignore a discrepancy between file name and entity name
844
852
  */
845
853
 
846
854
  /**
847
- * @@@
855
+ * This error indicates that the promptbook in a markdown format cannot be parsed into a valid promptbook object
848
856
  *
849
- * @public exported from `@promptbook/utils`
857
+ * @public exported from `@promptbook/core`
850
858
  */
851
- function deepClone(objectValue) {
852
- return JSON.parse(JSON.stringify(objectValue));
853
- /*
854
- TODO: [🧠] Is there a better implementation?
855
- > const propertyNames = Object.getOwnPropertyNames(objectValue);
856
- > for (const propertyName of propertyNames) {
857
- > const value = (objectValue as really_any)[propertyName];
858
- > if (value && typeof value === 'object') {
859
- > deepClone(value);
860
- > }
861
- > }
862
- > return Object.assign({}, objectValue);
863
- */
859
+ class ParseError extends Error {
860
+ constructor(message) {
861
+ super(message);
862
+ this.name = 'ParseError';
863
+ Object.setPrototypeOf(this, ParseError.prototype);
864
+ }
864
865
  }
865
866
  /**
866
- * TODO: [🧠] Is there a way how to meaningfully test this utility
867
+ * TODO: Maybe split `ParseError` and `ApplyError`
867
868
  */
868
869
 
869
870
  /**
870
- * Utility to export a JSON object from a function
871
- *
872
- * 1) Checks if the value is serializable as JSON
873
- * 2) Makes a deep clone of the object
874
- * 2) Orders the object properties
875
- * 2) Deeply freezes the cloned object
871
+ * Generates random token
876
872
  *
877
- * Note: This function does not mutates the given object
873
+ * Note: This function is cryptographically secure (it uses crypto.randomBytes internally)
878
874
  *
879
- * @returns The same type of object as the input but read-only and re-ordered
880
- * @public exported from `@promptbook/utils`
875
+ * @private internal helper function
876
+ * @returns secure random token
881
877
  */
882
- function exportJson(options) {
883
- const { name, value, order, message } = options;
884
- checkSerializableAsJson({ name, value, message });
885
- const orderedValue =
886
- // TODO: Fix error "Type instantiation is excessively deep and possibly infinite."
887
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
888
- // @ts-ignore
889
- order === undefined
890
- ? deepClone(value)
891
- : orderJson({
892
- value: value,
893
- // <- Note: checkSerializableAsJson asserts that the value is serializable as JSON
894
- order: order,
895
- });
896
- $deepFreeze(orderedValue);
897
- return orderedValue;
878
+ function $randomToken(randomness) {
879
+ return randomBytes(randomness).toString('hex');
898
880
  }
899
881
  /**
900
- * TODO: [🧠] Is there a way how to meaningfully test this utility
882
+ * TODO: Maybe use nanoid instead https://github.com/ai/nanoid
901
883
  */
902
884
 
903
885
  /**
904
- * The names of the parameters that are reserved for special purposes
886
+ * This error indicates errors during the execution of the pipeline
905
887
  *
906
888
  * @public exported from `@promptbook/core`
907
889
  */
908
- exportJson({
909
- name: 'RESERVED_PARAMETER_NAMES',
910
- message: `The names of the parameters that are reserved for special purposes`,
911
- value: [
912
- 'content',
913
- 'context',
914
- 'knowledge',
915
- 'examples',
916
- 'modelName',
917
- 'currentDate',
918
- // <- TODO: list here all command names
919
- // <- TODO: Add more like 'date', 'modelName',...
920
- // <- TODO: Add [emoji] + instructions ACRY when adding new reserved parameter
921
- ],
890
+ class PipelineExecutionError extends Error {
891
+ constructor(message) {
892
+ // Added id parameter
893
+ super(message);
894
+ this.name = 'PipelineExecutionError';
895
+ // TODO: [🐙] DRY - Maybe $randomId
896
+ this.id = `error-${$randomToken(8 /* <- TODO: To global config + Use Base58 to avoid similar char conflicts */)}`;
897
+ Object.setPrototypeOf(this, PipelineExecutionError.prototype);
898
+ }
899
+ }
900
+ /**
901
+ * TODO: [🧠][🌂] Add id to all errors
902
+ */
903
+
904
+ /**
905
+ * Index of all javascript errors
906
+ *
907
+ * @private for internal usage
908
+ */
909
+ ({
910
+ Error,
911
+ EvalError,
912
+ RangeError,
913
+ ReferenceError,
914
+ SyntaxError,
915
+ TypeError,
916
+ URIError,
917
+ AggregateError,
918
+ /*
919
+ Note: Not widely supported
920
+ > InternalError,
921
+ > ModuleError,
922
+ > HeapError,
923
+ > WebAssemblyCompileError,
924
+ > WebAssemblyRuntimeError,
925
+ */
922
926
  });
923
927
  /**
924
928
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -1100,10 +1104,10 @@ function decapitalize(word) {
1100
1104
  }
1101
1105
 
1102
1106
  /**
1103
- * @@@
1107
+ * Normalizes a text string to SCREAMING_CASE (all uppercase with underscores).
1104
1108
  *
1105
- * @param text @@@
1106
- * @returns @@@
1109
+ * @param text The text string to be converted to SCREAMING_CASE format.
1110
+ * @returns The normalized text in SCREAMING_CASE format.
1107
1111
  * @example 'HELLO_WORLD'
1108
1112
  * @example 'I_LOVE_PROMPTBOOK'
1109
1113
  * @public exported from `@promptbook/utils`
@@ -1170,11 +1174,11 @@ function parseKeywordsFromString(input) {
1170
1174
  }
1171
1175
 
1172
1176
  /**
1173
- * @@@
1177
+ * Converts a name string into a URI-compatible format.
1174
1178
  *
1175
- * @param name @@@
1176
- * @returns @@@
1177
- * @example @@@
1179
+ * @param name The string to be converted to a URI-compatible format.
1180
+ * @returns A URI-compatible string derived from the input name.
1181
+ * @example 'Hello World' -> 'hello-world'
1178
1182
  * @public exported from `@promptbook/utils`
1179
1183
  */
1180
1184
  function nameToUriPart(name) {
@@ -1188,11 +1192,11 @@ function nameToUriPart(name) {
1188
1192
  }
1189
1193
 
1190
1194
  /**
1191
- * @@@
1195
+ * Converts a given name into URI-compatible parts.
1192
1196
  *
1193
- * @param name @@@
1194
- * @returns @@@
1195
- * @example @@@
1197
+ * @param name The name to be converted into URI parts.
1198
+ * @returns An array of URI-compatible parts derived from the name.
1199
+ * @example 'Example Name' -> ['example', 'name']
1196
1200
  * @public exported from `@promptbook/utils`
1197
1201
  */
1198
1202
  function nameToUriParts(name) {
@@ -1214,10 +1218,10 @@ function normalizeTo_PascalCase(text) {
1214
1218
  }
1215
1219
 
1216
1220
  /**
1217
- * @@@
1221
+ * Normalizes a text string to snake_case format.
1218
1222
  *
1219
- * @param text @@@
1220
- * @returns @@@
1223
+ * @param text The text string to be converted to snake_case format.
1224
+ * @returns The normalized text in snake_case format.
1221
1225
  * @example 'hello_world'
1222
1226
  * @example 'i_love_promptbook'
1223
1227
  * @public exported from `@promptbook/utils`
@@ -1238,9 +1242,9 @@ function normalizeWhitespaces(sentence) {
1238
1242
  /**
1239
1243
  * Removes quotes from a string
1240
1244
  *
1241
- * Tip: This is very usefull for post-processing of the result of the LLM model
1245
+ * Tip: This is very useful for post-processing of the result of the LLM model
1242
1246
  * Note: This function removes only the same quotes from the beginning and the end of the string
1243
- * Note: There are two simmilar functions:
1247
+ * Note: There are two similar functions:
1244
1248
  * - `removeQuotes` which removes only bounding quotes
1245
1249
  * - `unwrapResult` which removes whole introduce sentence
1246
1250
  *
@@ -1252,7 +1256,7 @@ function removeQuotes(text) {
1252
1256
  if (text.startsWith('"') && text.endsWith('"')) {
1253
1257
  return text.slice(1, -1);
1254
1258
  }
1255
- if (text.startsWith('\'') && text.endsWith('\'')) {
1259
+ if (text.startsWith("'") && text.endsWith("'")) {
1256
1260
  return text.slice(1, -1);
1257
1261
  }
1258
1262
  return text;
@@ -1261,7 +1265,7 @@ function removeQuotes(text) {
1261
1265
  /**
1262
1266
  * Function trimCodeBlock will trim starting and ending code block from the string if it is present.
1263
1267
  *
1264
- * Note: This is usefull for post-processing of the result of the chat LLM model
1268
+ * Note: This is useful for post-processing of the result of the chat LLM model
1265
1269
  * when the model wraps the result in the (markdown) code block.
1266
1270
  *
1267
1271
  * @public exported from `@promptbook/utils`
@@ -1280,7 +1284,7 @@ function trimCodeBlock(value) {
1280
1284
  /**
1281
1285
  * Function trimEndOfCodeBlock will remove ending code block from the string if it is present.
1282
1286
  *
1283
- * Note: This is usefull for post-processing of the result of the completion LLM model
1287
+ * Note: This is useful for post-processing of the result of the completion LLM model
1284
1288
  * if you want to start code block in the prompt but you don't want to end it in the result.
1285
1289
  *
1286
1290
  * @public exported from `@promptbook/utils`
@@ -1295,9 +1299,9 @@ function trimEndOfCodeBlock(value) {
1295
1299
  /**
1296
1300
  * Removes quotes and optional introduce text from a string
1297
1301
  *
1298
- * Tip: This is very usefull for post-processing of the result of the LLM model
1302
+ * Tip: This is very useful for post-processing of the result of the LLM model
1299
1303
  * Note: This function trims the text and removes whole introduce sentence if it is present
1300
- * Note: There are two simmilar functions:
1304
+ * Note: There are two similar functions:
1301
1305
  * - `removeQuotes` which removes only bounding quotes
1302
1306
  * - `unwrapResult` which removes whole introduce sentence
1303
1307
  *
@@ -1366,8 +1370,8 @@ function unwrapResult(text, options) {
1366
1370
  /**
1367
1371
  * Extracts all code blocks from markdown.
1368
1372
  *
1369
- * Note: There are multiple simmilar function:
1370
- * - `extractBlock` just extracts the content of the code block which is also used as build-in function for postprocessing
1373
+ * Note: There are multiple similar functions:
1374
+ * - `extractBlock` just extracts the content of the code block which is also used as built-in function for postprocessing
1371
1375
  * - `extractJsonBlock` extracts exactly one valid JSON code block
1372
1376
  * - `extractOneBlockFromMarkdown` extracts exactly one code block with language of the code block
1373
1377
  * - `extractAllBlocksFromMarkdown` extracts all code blocks with language of the code block
@@ -1417,7 +1421,7 @@ function extractAllBlocksFromMarkdown(markdown) {
1417
1421
  if (currentCodeBlock.content !== '') {
1418
1422
  currentCodeBlock.content += '\n';
1419
1423
  }
1420
- currentCodeBlock.content += line.split('\\`\\`\\`').join('```') /* <- TODO: Maybe make propper unescape */;
1424
+ currentCodeBlock.content += line.split('\\`\\`\\`').join('```') /* <- TODO: Maybe make proper unescape */;
1421
1425
  }
1422
1426
  }
1423
1427
  if (currentCodeBlock !== null) {
@@ -1434,8 +1438,8 @@ function extractAllBlocksFromMarkdown(markdown) {
1434
1438
  *
1435
1439
  * - When there are multiple or no code blocks the function throws a `ParseError`
1436
1440
  *
1437
- * Note: There are multiple simmilar function:
1438
- * - `extractBlock` just extracts the content of the code block which is also used as build-in function for postprocessing
1441
+ * Note: There are multiple similar functions:
1442
+ * - `extractBlock` just extracts the content of the code block which is also used as built-in function for postprocessing
1439
1443
  * - `extractJsonBlock` extracts exactly one valid JSON code block
1440
1444
  * - `extractOneBlockFromMarkdown` extracts exactly one code block with language of the code block
1441
1445
  * - `extractAllBlocksFromMarkdown` extracts all code blocks with language of the code block
@@ -1465,7 +1469,7 @@ function extractOneBlockFromMarkdown(markdown) {
1465
1469
  *
1466
1470
  * - When there are multiple or no code blocks the function throws a `ParseError`
1467
1471
  *
1468
- * Note: There are multiple simmilar function:
1472
+ * Note: There are multiple similar function:
1469
1473
  * - `extractBlock` just extracts the content of the code block which is also used as build-in function for postprocessing
1470
1474
  * - `extractJsonBlock` extracts exactly one valid JSON code block
1471
1475
  * - `extractOneBlockFromMarkdown` extracts exactly one code block with language of the code block
@@ -1536,7 +1540,7 @@ function preserve(func) {
1536
1540
  })();
1537
1541
  }
1538
1542
  /**
1539
- * TODO: Probbably remove in favour of `keepImported`
1543
+ * TODO: Probably remove in favour of `keepImported`
1540
1544
  * TODO: [1] This maybe does memory leak
1541
1545
  */
1542
1546
 
@@ -1740,7 +1744,7 @@ class JavascriptEvalExecutionTools {
1740
1744
  */
1741
1745
 
1742
1746
  /**
1743
- * Placeholder for better implementation of JavascriptExecutionTools - some propper sandboxing
1747
+ * Placeholder for better implementation of JavascriptExecutionTools - some proper sandboxing
1744
1748
  *
1745
1749
  * @alias JavascriptExecutionTools
1746
1750
  * @public exported from `@promptbook/javascript`
@@ -1755,7 +1759,11 @@ const trim = (str) => str.trim();
1755
1759
  // TODO: DRY [🍯]
1756
1760
  const reverse = (str) => str.split('').reverse().join('');
1757
1761
  /**
1758
- * @@@
1762
+ * Collection of utility functions that can be used for post-processing model outputs.
1763
+ * These functions help transform, extract, or format the raw model responses.
1764
+ *
1765
+ * These utilities range from simple string manipulations to markdown processing
1766
+ * and formatting functions for specific types of output.
1759
1767
  *
1760
1768
  * @public exported from `@promptbook/javascript`
1761
1769
  */