@promptbook/javascript 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 +507 -499
  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 +507 -499
  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/umd/index.umd.js CHANGED
@@ -23,7 +23,7 @@
23
23
  * @generated
24
24
  * @see https://github.com/webgptorg/promptbook
25
25
  */
26
- const PROMPTBOOK_ENGINE_VERSION = '0.92.0-3';
26
+ const PROMPTBOOK_ENGINE_VERSION = '0.92.0-31';
27
27
  /**
28
28
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
29
29
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -79,7 +79,7 @@
79
79
  const SMALL_NUMBER = 0.001;
80
80
  // <- TODO: [🧜‍♂️]
81
81
  /**
82
- * @@@
82
+ * Default settings for parsing and generating CSV files in Promptbook.
83
83
  *
84
84
  * @public exported from `@promptbook/core`
85
85
  */
@@ -94,6 +94,48 @@
94
94
  * TODO: [🧠][🧜‍♂️] Maybe join remoteServerUrl and path into single value
95
95
  */
96
96
 
97
+ /**
98
+ * Orders JSON object by keys
99
+ *
100
+ * @returns The same type of object as the input re-ordered
101
+ * @public exported from `@promptbook/utils`
102
+ */
103
+ function orderJson(options) {
104
+ const { value, order } = options;
105
+ const orderedValue = {
106
+ ...(order === undefined ? {} : Object.fromEntries(order.map((key) => [key, undefined]))),
107
+ ...value,
108
+ };
109
+ return orderedValue;
110
+ }
111
+
112
+ /**
113
+ * Freezes the given object and all its nested objects recursively
114
+ *
115
+ * Note: `$` is used to indicate that this function is not a pure function - it mutates given object
116
+ * Note: This function mutates the object and returns the original (but mutated-deep-freezed) object
117
+ *
118
+ * @returns The same object as the input, but deeply frozen
119
+ * @public exported from `@promptbook/utils`
120
+ */
121
+ function $deepFreeze(objectValue) {
122
+ if (Array.isArray(objectValue)) {
123
+ return Object.freeze(objectValue.map((item) => $deepFreeze(item)));
124
+ }
125
+ const propertyNames = Object.getOwnPropertyNames(objectValue);
126
+ for (const propertyName of propertyNames) {
127
+ const value = objectValue[propertyName];
128
+ if (value && typeof value === 'object') {
129
+ $deepFreeze(value);
130
+ }
131
+ }
132
+ Object.freeze(objectValue);
133
+ return objectValue;
134
+ }
135
+ /**
136
+ * TODO: [🧠] Is there a way how to meaningfully test this utility
137
+ */
138
+
97
139
  /**
98
140
  * Make error report URL for the given error
99
141
  *
@@ -163,70 +205,341 @@
163
205
  }
164
206
 
165
207
  /**
166
- * @@@
208
+ * This error type indicates that somewhere in the code non-Error object was thrown and it was wrapped into the `WrappedError`
167
209
  *
168
- * @param text @@@
169
- * @param _isFirstLetterCapital @@@
170
- * @returns @@@
171
- * @example 'helloWorld'
172
- * @example 'iLovePromptbook'
210
+ * @public exported from `@promptbook/core`
211
+ */
212
+ class WrappedError extends Error {
213
+ constructor(whatWasThrown) {
214
+ const tag = `[🤮]`;
215
+ console.error(tag, whatWasThrown);
216
+ super(spaceTrim.spaceTrim(`
217
+ Non-Error object was thrown
218
+
219
+ Note: Look for ${tag} in the console for more details
220
+ Please report issue on ${ADMIN_EMAIL}
221
+ `));
222
+ this.name = 'WrappedError';
223
+ Object.setPrototypeOf(this, WrappedError.prototype);
224
+ }
225
+ }
226
+
227
+ /**
228
+ * Helper used in catch blocks to assert that the error is an instance of `Error`
229
+ *
230
+ * @param whatWasThrown Any object that was thrown
231
+ * @returns Nothing if the error is an instance of `Error`
232
+ * @throws `WrappedError` or `UnexpectedError` if the error is not standard
233
+ *
234
+ * @private within the repository
235
+ */
236
+ function assertsError(whatWasThrown) {
237
+ // Case 1: Handle error which was rethrown as `WrappedError`
238
+ if (whatWasThrown instanceof WrappedError) {
239
+ const wrappedError = whatWasThrown;
240
+ throw wrappedError;
241
+ }
242
+ // Case 2: Handle unexpected errors
243
+ if (whatWasThrown instanceof UnexpectedError) {
244
+ const unexpectedError = whatWasThrown;
245
+ throw unexpectedError;
246
+ }
247
+ // Case 3: Handle standard errors - keep them up to consumer
248
+ if (whatWasThrown instanceof Error) {
249
+ return;
250
+ }
251
+ // Case 4: Handle non-standard errors - wrap them into `WrappedError` and throw
252
+ throw new WrappedError(whatWasThrown);
253
+ }
254
+
255
+ /**
256
+ * Checks if the value is [🚉] serializable as JSON
257
+ * If not, throws an UnexpectedError with a rich error message and tracking
258
+ *
259
+ * - Almost all primitives are serializable BUT:
260
+ * - `undefined` is not serializable
261
+ * - `NaN` is not serializable
262
+ * - Objects and arrays are serializable if all their properties are serializable
263
+ * - Functions are not serializable
264
+ * - Circular references are not serializable
265
+ * - `Date` objects are not serializable
266
+ * - `Map` and `Set` objects are not serializable
267
+ * - `RegExp` objects are not serializable
268
+ * - `Error` objects are not serializable
269
+ * - `Symbol` objects are not serializable
270
+ * - And much more...
271
+ *
272
+ * @throws UnexpectedError if the value is not serializable as JSON
173
273
  * @public exported from `@promptbook/utils`
174
274
  */
175
- function normalizeTo_camelCase(text, _isFirstLetterCapital = false) {
176
- let charType;
177
- let lastCharType = null;
178
- let normalizedName = '';
179
- for (const char of text) {
180
- let normalizedChar;
181
- if (/^[a-z]$/.test(char)) {
182
- charType = 'LOWERCASE';
183
- normalizedChar = char;
275
+ function checkSerializableAsJson(options) {
276
+ const { value, name, message } = options;
277
+ if (value === undefined) {
278
+ throw new UnexpectedError(`${name} is undefined`);
279
+ }
280
+ else if (value === null) {
281
+ return;
282
+ }
283
+ else if (typeof value === 'boolean') {
284
+ return;
285
+ }
286
+ else if (typeof value === 'number' && !isNaN(value)) {
287
+ return;
288
+ }
289
+ else if (typeof value === 'string') {
290
+ return;
291
+ }
292
+ else if (typeof value === 'symbol') {
293
+ throw new UnexpectedError(`${name} is symbol`);
294
+ }
295
+ else if (typeof value === 'function') {
296
+ throw new UnexpectedError(`${name} is function`);
297
+ }
298
+ else if (typeof value === 'object' && Array.isArray(value)) {
299
+ for (let i = 0; i < value.length; i++) {
300
+ checkSerializableAsJson({ name: `${name}[${i}]`, value: value[i], message });
184
301
  }
185
- else if (/^[A-Z]$/.test(char)) {
186
- charType = 'UPPERCASE';
187
- normalizedChar = char.toLowerCase();
302
+ }
303
+ else if (typeof value === 'object') {
304
+ if (value instanceof Date) {
305
+ throw new UnexpectedError(spaceTrim__default["default"]((block) => `
306
+ \`${name}\` is Date
307
+
308
+ Use \`string_date_iso8601\` instead
309
+
310
+ Additional message for \`${name}\`:
311
+ ${block(message || '(nothing)')}
312
+ `));
188
313
  }
189
- else if (/^[0-9]$/.test(char)) {
190
- charType = 'NUMBER';
191
- normalizedChar = char;
314
+ else if (value instanceof Map) {
315
+ throw new UnexpectedError(`${name} is Map`);
192
316
  }
193
- else {
194
- charType = 'OTHER';
195
- normalizedChar = '';
317
+ else if (value instanceof Set) {
318
+ throw new UnexpectedError(`${name} is Set`);
196
319
  }
197
- if (!lastCharType) {
198
- if (_isFirstLetterCapital) {
199
- normalizedChar = normalizedChar.toUpperCase(); //TODO: DRY
200
- }
320
+ else if (value instanceof RegExp) {
321
+ throw new UnexpectedError(`${name} is RegExp`);
201
322
  }
202
- else if (charType !== lastCharType &&
203
- !(charType === 'LOWERCASE' && lastCharType === 'UPPERCASE') &&
204
- !(lastCharType === 'NUMBER') &&
205
- !(charType === 'NUMBER')) {
206
- normalizedChar = normalizedChar.toUpperCase(); //TODO: [🌺] DRY
323
+ else if (value instanceof Error) {
324
+ throw new UnexpectedError(spaceTrim__default["default"]((block) => `
325
+ \`${name}\` is unserialized Error
326
+
327
+ Use function \`serializeError\`
328
+
329
+ Additional message for \`${name}\`:
330
+ ${block(message || '(nothing)')}
331
+
332
+ `));
333
+ }
334
+ else {
335
+ for (const [subName, subValue] of Object.entries(value)) {
336
+ if (subValue === undefined) {
337
+ // Note: undefined in object is serializable - it is just omited
338
+ continue;
339
+ }
340
+ checkSerializableAsJson({ name: `${name}.${subName}`, value: subValue, message });
341
+ }
342
+ try {
343
+ JSON.stringify(value); // <- TODO: [0]
344
+ }
345
+ catch (error) {
346
+ assertsError(error);
347
+ throw new UnexpectedError(spaceTrim__default["default"]((block) => `
348
+ \`${name}\` is not serializable
349
+
350
+ ${block(error.stack || error.message)}
351
+
352
+ Additional message for \`${name}\`:
353
+ ${block(message || '(nothing)')}
354
+ `));
355
+ }
356
+ /*
357
+ TODO: [0] Is there some more elegant way to check circular references?
358
+ const seen = new Set();
359
+ const stack = [{ value }];
360
+ while (stack.length > 0) {
361
+ const { value } = stack.pop()!;
362
+ if (typeof value === 'object' && value !== null) {
363
+ if (seen.has(value)) {
364
+ throw new UnexpectedError(`${name} has circular reference`);
365
+ }
366
+ seen.add(value);
367
+ if (Array.isArray(value)) {
368
+ stack.push(...value.map((value) => ({ value })));
369
+ } else {
370
+ stack.push(...Object.values(value).map((value) => ({ value })));
371
+ }
372
+ }
373
+ }
374
+ */
375
+ return;
207
376
  }
208
- normalizedName += normalizedChar;
209
- lastCharType = charType;
210
377
  }
211
- return normalizedName;
378
+ else {
379
+ throw new UnexpectedError(spaceTrim__default["default"]((block) => `
380
+ \`${name}\` is unknown type
381
+
382
+ Additional message for \`${name}\`:
383
+ ${block(message || '(nothing)')}
384
+ `));
385
+ }
212
386
  }
213
387
  /**
214
- * TODO: [🌺] Use some intermediate util splitWords
388
+ * TODO: Can be return type more type-safe? like `asserts options.value is JsonValue`
389
+ * TODO: [🧠][main] !!3 In-memory cache of same values to prevent multiple checks
390
+ * Note: [🐠] This is how `checkSerializableAsJson` + `isSerializableAsJson` together can just retun true/false or rich error message
215
391
  */
216
392
 
217
393
  /**
218
- * Removes emojis from a string and fix whitespaces
394
+ * Creates a deep clone of the given object
219
395
  *
220
- * @param text with emojis
221
- * @returns text without emojis
396
+ * Note: This method only works for objects that are fully serializable to JSON and do not contain functions, Dates, or special types.
397
+ *
398
+ * @param objectValue The object to clone.
399
+ * @returns A deep, writable clone of the input object.
222
400
  * @public exported from `@promptbook/utils`
223
401
  */
224
- function removeEmojis(text) {
225
- // Replace emojis (and also ZWJ sequence) with hyphens
226
- text = text.replace(/(\p{Extended_Pictographic})\p{Modifier_Symbol}/gu, '$1');
227
- text = text.replace(/(\p{Extended_Pictographic})[\u{FE00}-\u{FE0F}]/gu, '$1');
228
- text = text.replace(/(\p{Extended_Pictographic})(\u{200D}\p{Extended_Pictographic})*/gu, '$1');
229
- text = text.replace(/\p{Extended_Pictographic}/gu, '');
402
+ function deepClone(objectValue) {
403
+ return JSON.parse(JSON.stringify(objectValue));
404
+ /*
405
+ TODO: [🧠] Is there a better implementation?
406
+ > const propertyNames = Object.getOwnPropertyNames(objectValue);
407
+ > for (const propertyName of propertyNames) {
408
+ > const value = (objectValue as really_any)[propertyName];
409
+ > if (value && typeof value === 'object') {
410
+ > deepClone(value);
411
+ > }
412
+ > }
413
+ > return Object.assign({}, objectValue);
414
+ */
415
+ }
416
+ /**
417
+ * TODO: [🧠] Is there a way how to meaningfully test this utility
418
+ */
419
+
420
+ /**
421
+ * Utility to export a JSON object from a function
422
+ *
423
+ * 1) Checks if the value is serializable as JSON
424
+ * 2) Makes a deep clone of the object
425
+ * 2) Orders the object properties
426
+ * 2) Deeply freezes the cloned object
427
+ *
428
+ * Note: This function does not mutates the given object
429
+ *
430
+ * @returns The same type of object as the input but read-only and re-ordered
431
+ * @public exported from `@promptbook/utils`
432
+ */
433
+ function exportJson(options) {
434
+ const { name, value, order, message } = options;
435
+ checkSerializableAsJson({ name, value, message });
436
+ const orderedValue =
437
+ // TODO: Fix error "Type instantiation is excessively deep and possibly infinite."
438
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
439
+ // @ts-ignore
440
+ order === undefined
441
+ ? deepClone(value)
442
+ : orderJson({
443
+ value: value,
444
+ // <- Note: checkSerializableAsJson asserts that the value is serializable as JSON
445
+ order: order,
446
+ });
447
+ $deepFreeze(orderedValue);
448
+ return orderedValue;
449
+ }
450
+ /**
451
+ * TODO: [🧠] Is there a way how to meaningfully test this utility
452
+ */
453
+
454
+ /**
455
+ * The names of the parameters that are reserved for special purposes
456
+ *
457
+ * @public exported from `@promptbook/core`
458
+ */
459
+ exportJson({
460
+ name: 'RESERVED_PARAMETER_NAMES',
461
+ message: `The names of the parameters that are reserved for special purposes`,
462
+ value: [
463
+ 'content',
464
+ 'context',
465
+ 'knowledge',
466
+ 'examples',
467
+ 'modelName',
468
+ 'currentDate',
469
+ // <- TODO: list here all command names
470
+ // <- TODO: Add more like 'date', 'modelName',...
471
+ // <- TODO: Add [emoji] + instructions ACRY when adding new reserved parameter
472
+ ],
473
+ });
474
+ /**
475
+ * Note: [💞] Ignore a discrepancy between file name and entity name
476
+ */
477
+
478
+ /**
479
+ * Normalizes a given text to camelCase format.
480
+ *
481
+ * @param text The text to be normalized.
482
+ * @param _isFirstLetterCapital Whether the first letter should be capitalized.
483
+ * @returns The camelCase formatted string.
484
+ * @example 'helloWorld'
485
+ * @example 'iLovePromptbook'
486
+ * @public exported from `@promptbook/utils`
487
+ */
488
+ function normalizeTo_camelCase(text, _isFirstLetterCapital = false) {
489
+ let charType;
490
+ let lastCharType = null;
491
+ let normalizedName = '';
492
+ for (const char of text) {
493
+ let normalizedChar;
494
+ if (/^[a-z]$/.test(char)) {
495
+ charType = 'LOWERCASE';
496
+ normalizedChar = char;
497
+ }
498
+ else if (/^[A-Z]$/.test(char)) {
499
+ charType = 'UPPERCASE';
500
+ normalizedChar = char.toLowerCase();
501
+ }
502
+ else if (/^[0-9]$/.test(char)) {
503
+ charType = 'NUMBER';
504
+ normalizedChar = char;
505
+ }
506
+ else {
507
+ charType = 'OTHER';
508
+ normalizedChar = '';
509
+ }
510
+ if (!lastCharType) {
511
+ if (_isFirstLetterCapital) {
512
+ normalizedChar = normalizedChar.toUpperCase(); //TODO: DRY
513
+ }
514
+ }
515
+ else if (charType !== lastCharType &&
516
+ !(charType === 'LOWERCASE' && lastCharType === 'UPPERCASE') &&
517
+ !(lastCharType === 'NUMBER') &&
518
+ !(charType === 'NUMBER')) {
519
+ normalizedChar = normalizedChar.toUpperCase(); //TODO: [🌺] DRY
520
+ }
521
+ normalizedName += normalizedChar;
522
+ lastCharType = charType;
523
+ }
524
+ return normalizedName;
525
+ }
526
+ /**
527
+ * TODO: [🌺] Use some intermediate util splitWords
528
+ */
529
+
530
+ /**
531
+ * Removes emojis from a string and fix whitespaces
532
+ *
533
+ * @param text with emojis
534
+ * @returns text without emojis
535
+ * @public exported from `@promptbook/utils`
536
+ */
537
+ function removeEmojis(text) {
538
+ // Replace emojis (and also ZWJ sequence) with hyphens
539
+ text = text.replace(/(\p{Extended_Pictographic})\p{Modifier_Symbol}/gu, '$1');
540
+ text = text.replace(/(\p{Extended_Pictographic})[\u{FE00}-\u{FE0F}]/gu, '$1');
541
+ text = text.replace(/(\p{Extended_Pictographic})(\u{200D}\p{Extended_Pictographic})*/gu, '$1');
542
+ text = text.replace(/\p{Extended_Pictographic}/gu, '');
230
543
  return text;
231
544
  }
232
545
 
@@ -455,474 +768,165 @@
455
768
  const letters = defaultDiacriticsRemovalMap[i].letters;
456
769
  // tslint:disable-next-line: prefer-for-of
457
770
  for (let j = 0; j < letters.length; j++) {
458
- DIACRITIC_VARIANTS_LETTERS[letters[j]] = defaultDiacriticsRemovalMap[i].base;
459
- }
460
- }
461
- // <- TODO: [🍓] Put to maker function to save execution time if not needed
462
- /*
463
- @see https://stackoverflow.com/questions/990904/remove-accents-diacritics-in-a-string-in-javascript
464
- Licensed under the Apache License, Version 2.0 (the "License");
465
- you may not use this file except in compliance with the License.
466
- You may obtain a copy of the License at
467
-
468
- http://www.apache.org/licenses/LICENSE-2.0
469
-
470
- Unless required by applicable law or agreed to in writing, software
471
- distributed under the License is distributed on an "AS IS" BASIS,
472
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
473
- See the License for the specific language governing permissions and
474
- limitations under the License.
475
- */
476
-
477
- /**
478
- * @@@
479
- *
480
- * @param input @@@
481
- * @returns @@@
482
- * @public exported from `@promptbook/utils`
483
- */
484
- function removeDiacritics(input) {
485
- /*eslint no-control-regex: "off"*/
486
- return input.replace(/[^\u0000-\u007E]/g, (a) => {
487
- return DIACRITIC_VARIANTS_LETTERS[a] || a;
488
- });
489
- }
490
- /**
491
- * TODO: [Ж] Variant for cyrillic (and in general non-latin) letters
492
- */
493
-
494
- /**
495
- * @@@
496
- *
497
- * @param text @@@
498
- * @returns @@@
499
- * @example 'hello-world'
500
- * @example 'i-love-promptbook'
501
- * @public exported from `@promptbook/utils`
502
- */
503
- function normalizeToKebabCase(text) {
504
- text = removeDiacritics(text);
505
- let charType;
506
- let lastCharType = 'OTHER';
507
- let normalizedName = '';
508
- for (const char of text) {
509
- let normalizedChar;
510
- if (/^[a-z]$/.test(char)) {
511
- charType = 'LOWERCASE';
512
- normalizedChar = char;
513
- }
514
- else if (/^[A-Z]$/.test(char)) {
515
- charType = 'UPPERCASE';
516
- normalizedChar = char.toLowerCase();
517
- }
518
- else if (/^[0-9]$/.test(char)) {
519
- charType = 'NUMBER';
520
- normalizedChar = char;
521
- }
522
- else {
523
- charType = 'OTHER';
524
- normalizedChar = '-';
525
- }
526
- if (charType !== lastCharType &&
527
- !(lastCharType === 'UPPERCASE' && charType === 'LOWERCASE') &&
528
- !(lastCharType === 'NUMBER') &&
529
- !(charType === 'NUMBER')) {
530
- normalizedName += '-';
531
- }
532
- normalizedName += normalizedChar;
533
- lastCharType = charType;
534
- }
535
- normalizedName = normalizedName.split(/-+/g).join('-');
536
- normalizedName = normalizedName.split(/-?\/-?/g).join('/');
537
- normalizedName = normalizedName.replace(/^-/, '');
538
- normalizedName = normalizedName.replace(/-$/, '');
539
- return normalizedName;
540
- }
541
- /**
542
- * Note: [💞] Ignore a discrepancy between file name and entity name
543
- */
544
-
545
- /**
546
- * This error indicates that the promptbook in a markdown format cannot be parsed into a valid promptbook object
547
- *
548
- * @public exported from `@promptbook/core`
549
- */
550
- class ParseError extends Error {
551
- constructor(message) {
552
- super(message);
553
- this.name = 'ParseError';
554
- Object.setPrototypeOf(this, ParseError.prototype);
555
- }
556
- }
557
- /**
558
- * TODO: Maybe split `ParseError` and `ApplyError`
559
- */
560
-
561
- /**
562
- * Generates random token
563
- *
564
- * Note: This function is cryptographically secure (it uses crypto.randomBytes internally)
565
- *
566
- * @private internal helper function
567
- * @returns secure random token
568
- */
569
- function $randomToken(randomness) {
570
- return crypto.randomBytes(randomness).toString('hex');
571
- }
572
- /**
573
- * TODO: Maybe use nanoid instead https://github.com/ai/nanoid
574
- */
575
-
576
- /**
577
- * This error indicates errors during the execution of the pipeline
578
- *
579
- * @public exported from `@promptbook/core`
580
- */
581
- class PipelineExecutionError extends Error {
582
- constructor(message) {
583
- // Added id parameter
584
- super(message);
585
- this.name = 'PipelineExecutionError';
586
- // TODO: [🐙] DRY - Maybe $randomId
587
- this.id = `error-${$randomToken(8 /* <- TODO: To global config + Use Base58 to avoid simmilar char conflicts */)}`;
588
- Object.setPrototypeOf(this, PipelineExecutionError.prototype);
589
- }
590
- }
591
- /**
592
- * TODO: [🧠][🌂] Add id to all errors
593
- */
594
-
595
- /**
596
- * This error type indicates that somewhere in the code non-Error object was thrown and it was wrapped into the `WrappedError`
597
- *
598
- * @public exported from `@promptbook/core`
599
- */
600
- class WrappedError extends Error {
601
- constructor(whatWasThrown) {
602
- const tag = `[🤮]`;
603
- console.error(tag, whatWasThrown);
604
- super(spaceTrim.spaceTrim(`
605
- Non-Error object was thrown
606
-
607
- Note: Look for ${tag} in the console for more details
608
- Please report issue on ${ADMIN_EMAIL}
609
- `));
610
- this.name = 'WrappedError';
611
- Object.setPrototypeOf(this, WrappedError.prototype);
612
- }
613
- }
614
-
615
- /**
616
- * Index of all javascript errors
617
- *
618
- * @private for internal usage
619
- */
620
- ({
621
- Error,
622
- EvalError,
623
- RangeError,
624
- ReferenceError,
625
- SyntaxError,
626
- TypeError,
627
- URIError,
628
- AggregateError,
629
- /*
630
- Note: Not widely supported
631
- > InternalError,
632
- > ModuleError,
633
- > HeapError,
634
- > WebAssemblyCompileError,
635
- > WebAssemblyRuntimeError,
636
- */
637
- });
638
- /**
639
- * Note: [💞] Ignore a discrepancy between file name and entity name
640
- */
641
-
642
- /**
643
- * Helper used in catch blocks to assert that the error is an instance of `Error`
644
- *
645
- * @param whatWasThrown Any object that was thrown
646
- * @returns Nothing if the error is an instance of `Error`
647
- * @throws `WrappedError` or `UnexpectedError` if the error is not standard
648
- *
649
- * @private within the repository
650
- */
651
- function assertsError(whatWasThrown) {
652
- // Case 1: Handle error which was rethrown as `WrappedError`
653
- if (whatWasThrown instanceof WrappedError) {
654
- const wrappedError = whatWasThrown;
655
- throw wrappedError;
656
- }
657
- // Case 2: Handle unexpected errors
658
- if (whatWasThrown instanceof UnexpectedError) {
659
- const unexpectedError = whatWasThrown;
660
- throw unexpectedError;
661
- }
662
- // Case 3: Handle standard errors - keep them up to consumer
663
- if (whatWasThrown instanceof Error) {
664
- return;
665
- }
666
- // Case 4: Handle non-standard errors - wrap them into `WrappedError` and throw
667
- throw new WrappedError(whatWasThrown);
668
- }
669
-
670
- /**
671
- * Orders JSON object by keys
672
- *
673
- * @returns The same type of object as the input re-ordered
674
- * @public exported from `@promptbook/utils`
675
- */
676
- function orderJson(options) {
677
- const { value, order } = options;
678
- const orderedValue = {
679
- ...(order === undefined ? {} : Object.fromEntries(order.map((key) => [key, undefined]))),
680
- ...value,
681
- };
682
- return orderedValue;
683
- }
684
-
685
- /**
686
- * Freezes the given object and all its nested objects recursively
687
- *
688
- * Note: `$` is used to indicate that this function is not a pure function - it mutates given object
689
- * Note: This function mutates the object and returns the original (but mutated-deep-freezed) object
690
- *
691
- * @returns The same object as the input, but deeply frozen
692
- * @public exported from `@promptbook/utils`
693
- */
694
- function $deepFreeze(objectValue) {
695
- if (Array.isArray(objectValue)) {
696
- return Object.freeze(objectValue.map((item) => $deepFreeze(item)));
697
- }
698
- const propertyNames = Object.getOwnPropertyNames(objectValue);
699
- for (const propertyName of propertyNames) {
700
- const value = objectValue[propertyName];
701
- if (value && typeof value === 'object') {
702
- $deepFreeze(value);
703
- }
704
- }
705
- Object.freeze(objectValue);
706
- return objectValue;
707
- }
708
- /**
709
- * TODO: [🧠] Is there a way how to meaningfully test this utility
710
- */
711
-
712
- /**
713
- * Checks if the value is [🚉] serializable as JSON
714
- * If not, throws an UnexpectedError with a rich error message and tracking
715
- *
716
- * - Almost all primitives are serializable BUT:
717
- * - `undefined` is not serializable
718
- * - `NaN` is not serializable
719
- * - Objects and arrays are serializable if all their properties are serializable
720
- * - Functions are not serializable
721
- * - Circular references are not serializable
722
- * - `Date` objects are not serializable
723
- * - `Map` and `Set` objects are not serializable
724
- * - `RegExp` objects are not serializable
725
- * - `Error` objects are not serializable
726
- * - `Symbol` objects are not serializable
727
- * - And much more...
728
- *
729
- * @throws UnexpectedError if the value is not serializable as JSON
730
- * @public exported from `@promptbook/utils`
731
- */
732
- function checkSerializableAsJson(options) {
733
- const { value, name, message } = options;
734
- if (value === undefined) {
735
- throw new UnexpectedError(`${name} is undefined`);
736
- }
737
- else if (value === null) {
738
- return;
739
- }
740
- else if (typeof value === 'boolean') {
741
- return;
742
- }
743
- else if (typeof value === 'number' && !isNaN(value)) {
744
- return;
745
- }
746
- else if (typeof value === 'string') {
747
- return;
748
- }
749
- else if (typeof value === 'symbol') {
750
- throw new UnexpectedError(`${name} is symbol`);
751
- }
752
- else if (typeof value === 'function') {
753
- throw new UnexpectedError(`${name} is function`);
754
- }
755
- else if (typeof value === 'object' && Array.isArray(value)) {
756
- for (let i = 0; i < value.length; i++) {
757
- checkSerializableAsJson({ name: `${name}[${i}]`, value: value[i], message });
758
- }
771
+ DIACRITIC_VARIANTS_LETTERS[letters[j]] = defaultDiacriticsRemovalMap[i].base;
759
772
  }
760
- else if (typeof value === 'object') {
761
- if (value instanceof Date) {
762
- throw new UnexpectedError(spaceTrim__default["default"]((block) => `
763
- \`${name}\` is Date
764
-
765
- Use \`string_date_iso8601\` instead
773
+ }
774
+ // <- TODO: [🍓] Put to maker function to save execution time if not needed
775
+ /*
776
+ @see https://stackoverflow.com/questions/990904/remove-accents-diacritics-in-a-string-in-javascript
777
+ Licensed under the Apache License, Version 2.0 (the "License");
778
+ you may not use this file except in compliance with the License.
779
+ You may obtain a copy of the License at
766
780
 
767
- Additional message for \`${name}\`:
768
- ${block(message || '(nothing)')}
769
- `));
770
- }
771
- else if (value instanceof Map) {
772
- throw new UnexpectedError(`${name} is Map`);
773
- }
774
- else if (value instanceof Set) {
775
- throw new UnexpectedError(`${name} is Set`);
776
- }
777
- else if (value instanceof RegExp) {
778
- throw new UnexpectedError(`${name} is RegExp`);
779
- }
780
- else if (value instanceof Error) {
781
- throw new UnexpectedError(spaceTrim__default["default"]((block) => `
782
- \`${name}\` is unserialized Error
781
+ http://www.apache.org/licenses/LICENSE-2.0
783
782
 
784
- Use function \`serializeError\`
783
+ Unless required by applicable law or agreed to in writing, software
784
+ distributed under the License is distributed on an "AS IS" BASIS,
785
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
786
+ See the License for the specific language governing permissions and
787
+ limitations under the License.
788
+ */
785
789
 
786
- Additional message for \`${name}\`:
787
- ${block(message || '(nothing)')}
790
+ /**
791
+ * Removes diacritic marks (accents) from characters in a string.
792
+ *
793
+ * @param input The string containing diacritics to be normalized.
794
+ * @returns The string with diacritics removed or normalized.
795
+ * @public exported from `@promptbook/utils`
796
+ */
797
+ function removeDiacritics(input) {
798
+ /*eslint no-control-regex: "off"*/
799
+ return input.replace(/[^\u0000-\u007E]/g, (a) => {
800
+ return DIACRITIC_VARIANTS_LETTERS[a] || a;
801
+ });
802
+ }
803
+ /**
804
+ * TODO: [Ж] Variant for cyrillic (and in general non-latin) letters
805
+ */
788
806
 
789
- `));
807
+ /**
808
+ * Converts a given text to kebab-case format.
809
+ *
810
+ * @param text The text to be converted.
811
+ * @returns The kebab-case formatted string.
812
+ * @example 'hello-world'
813
+ * @example 'i-love-promptbook'
814
+ * @public exported from `@promptbook/utils`
815
+ */
816
+ function normalizeToKebabCase(text) {
817
+ text = removeDiacritics(text);
818
+ let charType;
819
+ let lastCharType = 'OTHER';
820
+ let normalizedName = '';
821
+ for (const char of text) {
822
+ let normalizedChar;
823
+ if (/^[a-z]$/.test(char)) {
824
+ charType = 'LOWERCASE';
825
+ normalizedChar = char;
826
+ }
827
+ else if (/^[A-Z]$/.test(char)) {
828
+ charType = 'UPPERCASE';
829
+ normalizedChar = char.toLowerCase();
830
+ }
831
+ else if (/^[0-9]$/.test(char)) {
832
+ charType = 'NUMBER';
833
+ normalizedChar = char;
790
834
  }
791
835
  else {
792
- for (const [subName, subValue] of Object.entries(value)) {
793
- if (subValue === undefined) {
794
- // Note: undefined in object is serializable - it is just omited
795
- continue;
796
- }
797
- checkSerializableAsJson({ name: `${name}.${subName}`, value: subValue, message });
798
- }
799
- try {
800
- JSON.stringify(value); // <- TODO: [0]
801
- }
802
- catch (error) {
803
- assertsError(error);
804
- throw new UnexpectedError(spaceTrim__default["default"]((block) => `
805
- \`${name}\` is not serializable
806
-
807
- ${block(error.stack || error.message)}
808
-
809
- Additional message for \`${name}\`:
810
- ${block(message || '(nothing)')}
811
- `));
812
- }
813
- /*
814
- TODO: [0] Is there some more elegant way to check circular references?
815
- const seen = new Set();
816
- const stack = [{ value }];
817
- while (stack.length > 0) {
818
- const { value } = stack.pop()!;
819
- if (typeof value === 'object' && value !== null) {
820
- if (seen.has(value)) {
821
- throw new UnexpectedError(`${name} has circular reference`);
822
- }
823
- seen.add(value);
824
- if (Array.isArray(value)) {
825
- stack.push(...value.map((value) => ({ value })));
826
- } else {
827
- stack.push(...Object.values(value).map((value) => ({ value })));
828
- }
829
- }
830
- }
831
- */
832
- return;
836
+ charType = 'OTHER';
837
+ normalizedChar = '-';
833
838
  }
839
+ if (charType !== lastCharType &&
840
+ !(lastCharType === 'UPPERCASE' && charType === 'LOWERCASE') &&
841
+ !(lastCharType === 'NUMBER') &&
842
+ !(charType === 'NUMBER')) {
843
+ normalizedName += '-';
844
+ }
845
+ normalizedName += normalizedChar;
846
+ lastCharType = charType;
834
847
  }
835
- else {
836
- throw new UnexpectedError(spaceTrim__default["default"]((block) => `
837
- \`${name}\` is unknown type
838
-
839
- Additional message for \`${name}\`:
840
- ${block(message || '(nothing)')}
841
- `));
842
- }
848
+ normalizedName = normalizedName.split(/-+/g).join('-');
849
+ normalizedName = normalizedName.split(/-?\/-?/g).join('/');
850
+ normalizedName = normalizedName.replace(/^-/, '');
851
+ normalizedName = normalizedName.replace(/-$/, '');
852
+ return normalizedName;
843
853
  }
844
854
  /**
845
- * TODO: Can be return type more type-safe? like `asserts options.value is JsonValue`
846
- * TODO: [🧠][main] !!3 In-memory cache of same values to prevent multiple checks
847
- * Note: [🐠] This is how `checkSerializableAsJson` + `isSerializableAsJson` together can just retun true/false or rich error message
855
+ * Note: [💞] Ignore a discrepancy between file name and entity name
848
856
  */
849
857
 
850
858
  /**
851
- * @@@
859
+ * This error indicates that the promptbook in a markdown format cannot be parsed into a valid promptbook object
852
860
  *
853
- * @public exported from `@promptbook/utils`
861
+ * @public exported from `@promptbook/core`
854
862
  */
855
- function deepClone(objectValue) {
856
- return JSON.parse(JSON.stringify(objectValue));
857
- /*
858
- TODO: [🧠] Is there a better implementation?
859
- > const propertyNames = Object.getOwnPropertyNames(objectValue);
860
- > for (const propertyName of propertyNames) {
861
- > const value = (objectValue as really_any)[propertyName];
862
- > if (value && typeof value === 'object') {
863
- > deepClone(value);
864
- > }
865
- > }
866
- > return Object.assign({}, objectValue);
867
- */
863
+ class ParseError extends Error {
864
+ constructor(message) {
865
+ super(message);
866
+ this.name = 'ParseError';
867
+ Object.setPrototypeOf(this, ParseError.prototype);
868
+ }
868
869
  }
869
870
  /**
870
- * TODO: [🧠] Is there a way how to meaningfully test this utility
871
+ * TODO: Maybe split `ParseError` and `ApplyError`
871
872
  */
872
873
 
873
874
  /**
874
- * Utility to export a JSON object from a function
875
- *
876
- * 1) Checks if the value is serializable as JSON
877
- * 2) Makes a deep clone of the object
878
- * 2) Orders the object properties
879
- * 2) Deeply freezes the cloned object
875
+ * Generates random token
880
876
  *
881
- * Note: This function does not mutates the given object
877
+ * Note: This function is cryptographically secure (it uses crypto.randomBytes internally)
882
878
  *
883
- * @returns The same type of object as the input but read-only and re-ordered
884
- * @public exported from `@promptbook/utils`
879
+ * @private internal helper function
880
+ * @returns secure random token
885
881
  */
886
- function exportJson(options) {
887
- const { name, value, order, message } = options;
888
- checkSerializableAsJson({ name, value, message });
889
- const orderedValue =
890
- // TODO: Fix error "Type instantiation is excessively deep and possibly infinite."
891
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
892
- // @ts-ignore
893
- order === undefined
894
- ? deepClone(value)
895
- : orderJson({
896
- value: value,
897
- // <- Note: checkSerializableAsJson asserts that the value is serializable as JSON
898
- order: order,
899
- });
900
- $deepFreeze(orderedValue);
901
- return orderedValue;
882
+ function $randomToken(randomness) {
883
+ return crypto.randomBytes(randomness).toString('hex');
902
884
  }
903
885
  /**
904
- * TODO: [🧠] Is there a way how to meaningfully test this utility
886
+ * TODO: Maybe use nanoid instead https://github.com/ai/nanoid
905
887
  */
906
888
 
907
889
  /**
908
- * The names of the parameters that are reserved for special purposes
890
+ * This error indicates errors during the execution of the pipeline
909
891
  *
910
892
  * @public exported from `@promptbook/core`
911
893
  */
912
- exportJson({
913
- name: 'RESERVED_PARAMETER_NAMES',
914
- message: `The names of the parameters that are reserved for special purposes`,
915
- value: [
916
- 'content',
917
- 'context',
918
- 'knowledge',
919
- 'examples',
920
- 'modelName',
921
- 'currentDate',
922
- // <- TODO: list here all command names
923
- // <- TODO: Add more like 'date', 'modelName',...
924
- // <- TODO: Add [emoji] + instructions ACRY when adding new reserved parameter
925
- ],
894
+ class PipelineExecutionError extends Error {
895
+ constructor(message) {
896
+ // Added id parameter
897
+ super(message);
898
+ this.name = 'PipelineExecutionError';
899
+ // TODO: [🐙] DRY - Maybe $randomId
900
+ this.id = `error-${$randomToken(8 /* <- TODO: To global config + Use Base58 to avoid simmilar char conflicts */)}`;
901
+ Object.setPrototypeOf(this, PipelineExecutionError.prototype);
902
+ }
903
+ }
904
+ /**
905
+ * TODO: [🧠][🌂] Add id to all errors
906
+ */
907
+
908
+ /**
909
+ * Index of all javascript errors
910
+ *
911
+ * @private for internal usage
912
+ */
913
+ ({
914
+ Error,
915
+ EvalError,
916
+ RangeError,
917
+ ReferenceError,
918
+ SyntaxError,
919
+ TypeError,
920
+ URIError,
921
+ AggregateError,
922
+ /*
923
+ Note: Not widely supported
924
+ > InternalError,
925
+ > ModuleError,
926
+ > HeapError,
927
+ > WebAssemblyCompileError,
928
+ > WebAssemblyRuntimeError,
929
+ */
926
930
  });
927
931
  /**
928
932
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -1104,10 +1108,10 @@
1104
1108
  }
1105
1109
 
1106
1110
  /**
1107
- * @@@
1111
+ * Normalizes a text string to SCREAMING_CASE (all uppercase with underscores).
1108
1112
  *
1109
- * @param text @@@
1110
- * @returns @@@
1113
+ * @param text The text string to be converted to SCREAMING_CASE format.
1114
+ * @returns The normalized text in SCREAMING_CASE format.
1111
1115
  * @example 'HELLO_WORLD'
1112
1116
  * @example 'I_LOVE_PROMPTBOOK'
1113
1117
  * @public exported from `@promptbook/utils`
@@ -1174,11 +1178,11 @@
1174
1178
  }
1175
1179
 
1176
1180
  /**
1177
- * @@@
1181
+ * Converts a name string into a URI-compatible format.
1178
1182
  *
1179
- * @param name @@@
1180
- * @returns @@@
1181
- * @example @@@
1183
+ * @param name The string to be converted to a URI-compatible format.
1184
+ * @returns A URI-compatible string derived from the input name.
1185
+ * @example 'Hello World' -> 'hello-world'
1182
1186
  * @public exported from `@promptbook/utils`
1183
1187
  */
1184
1188
  function nameToUriPart(name) {
@@ -1192,11 +1196,11 @@
1192
1196
  }
1193
1197
 
1194
1198
  /**
1195
- * @@@
1199
+ * Converts a given name into URI-compatible parts.
1196
1200
  *
1197
- * @param name @@@
1198
- * @returns @@@
1199
- * @example @@@
1201
+ * @param name The name to be converted into URI parts.
1202
+ * @returns An array of URI-compatible parts derived from the name.
1203
+ * @example 'Example Name' -> ['example', 'name']
1200
1204
  * @public exported from `@promptbook/utils`
1201
1205
  */
1202
1206
  function nameToUriParts(name) {
@@ -1218,10 +1222,10 @@
1218
1222
  }
1219
1223
 
1220
1224
  /**
1221
- * @@@
1225
+ * Normalizes a text string to snake_case format.
1222
1226
  *
1223
- * @param text @@@
1224
- * @returns @@@
1227
+ * @param text The text string to be converted to snake_case format.
1228
+ * @returns The normalized text in snake_case format.
1225
1229
  * @example 'hello_world'
1226
1230
  * @example 'i_love_promptbook'
1227
1231
  * @public exported from `@promptbook/utils`
@@ -1759,7 +1763,11 @@
1759
1763
  // TODO: DRY [🍯]
1760
1764
  const reverse = (str) => str.split('').reverse().join('');
1761
1765
  /**
1762
- * @@@
1766
+ * Collection of utility functions that can be used for post-processing model outputs.
1767
+ * These functions help transform, extract, or format the raw model responses.
1768
+ *
1769
+ * These utilities range from simple string manipulations to markdown processing
1770
+ * and formatting functions for specific types of output.
1763
1771
  *
1764
1772
  * @public exported from `@promptbook/javascript`
1765
1773
  */