@promptbook/cli 0.100.0-45 → 0.100.0-47

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 (24) hide show
  1. package/esm/index.es.js +204 -107
  2. package/esm/index.es.js.map +1 -1
  3. package/esm/typings/src/_packages/components.index.d.ts +4 -0
  4. package/esm/typings/src/_packages/core.index.d.ts +2 -0
  5. package/esm/typings/src/_packages/types.index.d.ts +2 -6
  6. package/esm/typings/src/book-2.0/commitments/_misc/AgentModelRequirements.d.ts +1 -1
  7. package/esm/typings/src/book-components/Chat/Chat/Chat.d.ts +4 -10
  8. package/esm/typings/src/book-components/Chat/interfaces/ChatMessage.d.ts +12 -26
  9. package/esm/typings/src/book-components/Chat/interfaces/ChatParticipant.d.ts +30 -0
  10. package/esm/typings/src/book-components/Chat/utils/exportChatHistory.d.ts +2 -4
  11. package/esm/typings/src/book-components/Chat/utils/generatePdfContent.d.ts +2 -4
  12. package/esm/typings/src/book-components/Chat/utils/messagesToHtml.d.ts +2 -4
  13. package/esm/typings/src/book-components/Chat/utils/messagesToMarkdown.d.ts +2 -4
  14. package/esm/typings/src/book-components/Chat/utils/messagesToText.d.ts +2 -4
  15. package/esm/typings/src/config.d.ts +7 -0
  16. package/esm/typings/src/execution/ExecutionTask.d.ts +8 -0
  17. package/esm/typings/src/llm-providers/openai/OpenAiCompatibleExecutionTools.d.ts +8 -0
  18. package/esm/typings/src/playground/permanent/error-handling-playground.d.ts +5 -0
  19. package/esm/typings/src/utils/organization/preserve.d.ts +21 -0
  20. package/esm/typings/src/version.d.ts +1 -1
  21. package/package.json +1 -2
  22. package/umd/index.umd.js +208 -111
  23. package/umd/index.umd.js.map +1 -1
  24. package/esm/typings/src/scripting/javascript/utils/preserve.d.ts +0 -14
package/esm/index.es.js CHANGED
@@ -13,8 +13,9 @@ import { io } from 'socket.io-client';
13
13
  import { Subject } from 'rxjs';
14
14
  import { spawn } from 'child_process';
15
15
  import JSZip from 'jszip';
16
- import { format } from 'prettier';
17
16
  import parserHtml from 'prettier/parser-html';
17
+ import parserMarkdown from 'prettier/parser-markdown';
18
+ import { format } from 'prettier/standalone';
18
19
  import { parse, unparse } from 'papaparse';
19
20
  import { SHA256 } from 'crypto-js';
20
21
  import { lookup, extension } from 'mime-types';
@@ -47,7 +48,7 @@ const BOOK_LANGUAGE_VERSION = '1.0.0';
47
48
  * @generated
48
49
  * @see https://github.com/webgptorg/promptbook
49
50
  */
50
- const PROMPTBOOK_ENGINE_VERSION = '0.100.0-45';
51
+ const PROMPTBOOK_ENGINE_VERSION = '0.100.0-47';
51
52
  /**
52
53
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
53
54
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -376,6 +377,13 @@ const DEFAULT_GET_PIPELINE_COLLECTION_FUNCTION_NAME = `getPipelineCollection`;
376
377
  * @public exported from `@promptbook/core`
377
378
  */
378
379
  const DEFAULT_MAX_REQUESTS_PER_MINUTE = 60;
380
+ /**
381
+ * API request timeout in milliseconds
382
+ * Can be overridden via API_REQUEST_TIMEOUT environment variable
383
+ *
384
+ * @public exported from `@promptbook/core`
385
+ */
386
+ const API_REQUEST_TIMEOUT = parseInt(process.env.API_REQUEST_TIMEOUT || '90000');
379
387
  /**
380
388
  * Indicates whether pipeline logic validation is enabled. When true, the pipeline logic is checked for consistency.
381
389
  *
@@ -5131,7 +5139,7 @@ function prettifyMarkdown(content) {
5131
5139
  try {
5132
5140
  return format(content, {
5133
5141
  parser: 'markdown',
5134
- plugins: [parserHtml],
5142
+ plugins: [parserMarkdown, parserHtml],
5135
5143
  // TODO: DRY - make some import or auto-copy of .prettierrc
5136
5144
  endOfLine: 'lf',
5137
5145
  tabWidth: 4,
@@ -7596,64 +7604,74 @@ function createPipelineExecutor(options) {
7596
7604
  });
7597
7605
  });
7598
7606
  };
7599
- const pipelineExecutor = (inputParameters) => createTask({
7600
- taskType: 'EXECUTION',
7601
- title: pipeline.title,
7602
- taskProcessCallback(updateOngoingResult, updateTldr) {
7603
- return pipelineExecutorWithCallback(inputParameters, async (newOngoingResult) => {
7604
- var _a;
7605
- updateOngoingResult(newOngoingResult);
7606
- // Calculate and update tldr based on pipeline progress
7607
- const cv = newOngoingResult;
7608
- // Calculate progress based on pipeline tasks
7609
- const totalTasks = pipeline.tasks.length;
7610
- let completedTasks = 0;
7611
- let currentTaskName = '';
7612
- // Check execution report for completed tasks
7613
- if ((_a = cv === null || cv === void 0 ? void 0 : cv.executionReport) === null || _a === void 0 ? void 0 : _a.promptExecutions) {
7614
- const executedTaskTitles = new Set(cv.executionReport.promptExecutions.map((execution) => execution.prompt.title));
7615
- // Count completed tasks by matching titles
7616
- const completedTasksByTitle = pipeline.tasks.filter((task) => executedTaskTitles.has(task.title));
7617
- completedTasks = completedTasksByTitle.length;
7618
- // Find current task being executed (first task not yet completed)
7619
- const remainingTasks = pipeline.tasks.filter((task) => !executedTaskTitles.has(task.title));
7620
- if (remainingTasks.length > 0) {
7621
- currentTaskName = remainingTasks[0].name;
7607
+ const pipelineExecutor = (inputParameters) => {
7608
+ const startTime = new Date().getTime();
7609
+ return createTask({
7610
+ taskType: 'EXECUTION',
7611
+ title: pipeline.title,
7612
+ taskProcessCallback(updateOngoingResult, updateTldr) {
7613
+ return pipelineExecutorWithCallback(inputParameters, async (newOngoingResult) => {
7614
+ var _a, _b;
7615
+ updateOngoingResult(newOngoingResult);
7616
+ // Calculate and update tldr based on pipeline progress
7617
+ const cv = newOngoingResult;
7618
+ // Calculate progress based on parameters resolved vs total parameters
7619
+ const totalParameters = pipeline.parameters.filter(p => !p.isInput).length;
7620
+ let resolvedParameters = 0;
7621
+ let currentTaskTitle = '';
7622
+ // Get the resolved parameters from output parameters
7623
+ if (cv === null || cv === void 0 ? void 0 : cv.outputParameters) {
7624
+ // Count how many output parameters have non-empty values
7625
+ resolvedParameters = Object.values(cv.outputParameters).filter(value => value !== undefined && value !== null && String(value).trim() !== '').length;
7622
7626
  }
7623
- }
7624
- // Calculate progress percentage
7625
- let percent = totalTasks > 0 ? completedTasks / totalTasks : 0;
7626
- // Add time-based progress for current task (assuming 5 minutes total)
7627
- if (completedTasks < totalTasks) {
7628
- const elapsedMs = new Date().getTime() - new Date().getTime(); // Will be overridden by actual elapsed time in task
7629
- const totalMs = 5 * 60 * 1000; // 5 minutes
7630
- const timeProgress = Math.min(elapsedMs / totalMs, 1);
7631
- // Add partial progress for current task
7632
- percent += (1 / totalTasks) * timeProgress;
7633
- }
7634
- // Clamp to [0,1]
7635
- percent = Math.min(Math.max(percent, 0), 1);
7636
- // Generate message
7637
- let message = '';
7638
- if (currentTaskName) {
7639
- // Find the task to get its title
7640
- const currentTask = pipeline.tasks.find((task) => task.name === currentTaskName);
7641
- const taskTitle = (currentTask === null || currentTask === void 0 ? void 0 : currentTask.title) || currentTaskName;
7642
- message = `Working on task ${taskTitle}`;
7643
- }
7644
- else if (completedTasks === 0) {
7645
- message = 'Starting pipeline execution';
7646
- }
7647
- else {
7648
- message = `Processing pipeline (${completedTasks}/${totalTasks} tasks completed)`;
7649
- }
7650
- updateTldr({
7651
- percent: percent,
7652
- message,
7627
+ // Try to determine current task from execution report
7628
+ if (((_a = cv === null || cv === void 0 ? void 0 : cv.executionReport) === null || _a === void 0 ? void 0 : _a.promptExecutions) && cv.executionReport.promptExecutions.length > 0) {
7629
+ const lastExecution = cv.executionReport.promptExecutions[cv.executionReport.promptExecutions.length - 1];
7630
+ if ((_b = lastExecution === null || lastExecution === void 0 ? void 0 : lastExecution.prompt) === null || _b === void 0 ? void 0 : _b.title) {
7631
+ currentTaskTitle = lastExecution.prompt.title;
7632
+ }
7633
+ }
7634
+ // Calculate base progress percentage
7635
+ let percent = totalParameters > 0 ? resolvedParameters / totalParameters : 0;
7636
+ // Add time-based progress for current task if we haven't completed all parameters
7637
+ if (resolvedParameters < totalParameters) {
7638
+ const elapsedMs = new Date().getTime() - startTime;
7639
+ const estimatedTotalMs = totalParameters * 30 * 1000; // Estimate 30 seconds per parameter
7640
+ const timeProgress = Math.min(elapsedMs / estimatedTotalMs, 0.9); // Cap at 90% for time-based progress
7641
+ // If we have time progress but no parameter progress, show time progress
7642
+ if (percent === 0 && timeProgress > 0) {
7643
+ percent = Math.min(timeProgress, 0.1); // Show some progress but not more than 10%
7644
+ }
7645
+ else if (percent < 1) {
7646
+ // Add partial progress for current task
7647
+ const taskProgress = totalParameters > 0 ? (1 / totalParameters) * 0.5 : 0; // 50% of task progress
7648
+ percent = Math.min(percent + taskProgress, 0.95); // Cap at 95% until fully complete
7649
+ }
7650
+ }
7651
+ // Clamp to [0,1]
7652
+ percent = Math.min(Math.max(percent, 0), 1);
7653
+ // Generate message
7654
+ let message = '';
7655
+ if (currentTaskTitle) {
7656
+ message = `Executing: ${currentTaskTitle}`;
7657
+ }
7658
+ else if (resolvedParameters === 0) {
7659
+ message = 'Starting pipeline execution';
7660
+ }
7661
+ else if (resolvedParameters < totalParameters) {
7662
+ message = `Processing pipeline (${resolvedParameters}/${totalParameters} parameters resolved)`;
7663
+ }
7664
+ else {
7665
+ message = 'Completing pipeline execution';
7666
+ }
7667
+ updateTldr({
7668
+ percent: percent,
7669
+ message,
7670
+ });
7653
7671
  });
7654
- });
7655
- },
7656
- });
7672
+ },
7673
+ });
7674
+ };
7657
7675
  // <- TODO: Make types such as there is no need to do `as` for `createTask`
7658
7676
  return pipelineExecutor;
7659
7677
  }
@@ -7716,7 +7734,7 @@ async function preparePersona(personaDescription, tools, options) {
7716
7734
  const result = await preparePersonaExecutor({
7717
7735
  availableModels /* <- Note: Passing as JSON */,
7718
7736
  personaDescription,
7719
- }).asPromise();
7737
+ }).asPromise({ isCrashedOnError: true });
7720
7738
  const { outputParameters } = result;
7721
7739
  const { modelsRequirements: modelsRequirementsJson } = outputParameters;
7722
7740
  let modelsRequirementsUnchecked = jsonParse(modelsRequirementsJson);
@@ -8209,7 +8227,7 @@ async function preparePipeline(pipeline, tools, options) {
8209
8227
  });
8210
8228
  const result = await prepareTitleExecutor({
8211
8229
  book: sources.map(({ content }) => content).join('\n\n'),
8212
- }).asPromise();
8230
+ }).asPromise({ isCrashedOnError: true });
8213
8231
  const { outputParameters } = result;
8214
8232
  const { title: titleRaw } = outputParameters;
8215
8233
  if (isVerbose) {
@@ -12124,31 +12142,23 @@ function extractBlock(markdown) {
12124
12142
  return content;
12125
12143
  }
12126
12144
 
12145
+ /**
12146
+ * @private internal for `preserve`
12147
+ */
12148
+ const _preserved = [];
12127
12149
  /**
12128
12150
  * Does nothing, but preserves the function in the bundle
12129
12151
  * Compiler is tricked into thinking the function is used
12130
12152
  *
12131
12153
  * @param value any function to preserve
12132
12154
  * @returns nothing
12133
- * @private internal function of `JavascriptExecutionTools` and `JavascriptEvalExecutionTools`
12134
- */
12135
- function preserve(func) {
12136
- // Note: NOT calling the function
12137
- (async () => {
12138
- // TODO: [💩] Change to `await forEver` or `forTime(Infinity)`
12139
- await forTime(100000000);
12140
- // [1]
12141
- try {
12142
- await func();
12143
- }
12144
- finally {
12145
- // do nothing
12146
- }
12147
- })();
12155
+ * @private within the repository
12156
+ */
12157
+ function $preserve(...value) {
12158
+ _preserved.push(...value);
12148
12159
  }
12149
12160
  /**
12150
- * TODO: Probably remove in favour of `keepImported`
12151
- * TODO: [1] This maybe does memory leak
12161
+ * Note: [💞] Ignore a discrepancy between file name and entity name
12152
12162
  */
12153
12163
 
12154
12164
  // Note: [💎]
@@ -12176,25 +12186,25 @@ class JavascriptEvalExecutionTools {
12176
12186
  // Note: [💎]
12177
12187
  // Note: Using direct eval, following variables are in same scope as eval call so they are accessible from inside the evaluated script:
12178
12188
  const spaceTrim$1 = (_) => spaceTrim(_);
12179
- preserve(spaceTrim$1);
12189
+ $preserve(spaceTrim$1);
12180
12190
  const removeQuotes$1 = removeQuotes;
12181
- preserve(removeQuotes$1);
12191
+ $preserve(removeQuotes$1);
12182
12192
  const unwrapResult$1 = unwrapResult;
12183
- preserve(unwrapResult$1);
12193
+ $preserve(unwrapResult$1);
12184
12194
  const trimEndOfCodeBlock$1 = trimEndOfCodeBlock;
12185
- preserve(trimEndOfCodeBlock$1);
12195
+ $preserve(trimEndOfCodeBlock$1);
12186
12196
  const trimCodeBlock$1 = trimCodeBlock;
12187
- preserve(trimCodeBlock$1);
12197
+ $preserve(trimCodeBlock$1);
12188
12198
  // TODO: DRY [🍯]
12189
12199
  const trim = (str) => str.trim();
12190
- preserve(trim);
12200
+ $preserve(trim);
12191
12201
  // TODO: DRY [🍯]
12192
12202
  const reverse = (str) => str.split('').reverse().join('');
12193
- preserve(reverse);
12203
+ $preserve(reverse);
12194
12204
  const removeEmojis$1 = removeEmojis;
12195
- preserve(removeEmojis$1);
12205
+ $preserve(removeEmojis$1);
12196
12206
  const prettifyMarkdown$1 = prettifyMarkdown;
12197
- preserve(prettifyMarkdown$1);
12207
+ $preserve(prettifyMarkdown$1);
12198
12208
  //-------[n12:]---
12199
12209
  const capitalize$1 = capitalize;
12200
12210
  const decapitalize$1 = decapitalize;
@@ -12210,18 +12220,18 @@ class JavascriptEvalExecutionTools {
12210
12220
  // TODO: DRY [🍯]
12211
12221
  Array.from(parseKeywordsFromString(input)).join(', '); /* <- TODO: [🧠] What is the best format comma list, bullet list,...? */
12212
12222
  const normalizeTo_SCREAMING_CASE$1 = normalizeTo_SCREAMING_CASE;
12213
- preserve(capitalize$1);
12214
- preserve(decapitalize$1);
12215
- preserve(nameToUriPart$1);
12216
- preserve(nameToUriParts$1);
12217
- preserve(removeDiacritics$1);
12218
- preserve(normalizeWhitespaces$1);
12219
- preserve(normalizeToKebabCase$1);
12220
- preserve(normalizeTo_camelCase$1);
12221
- preserve(normalizeTo_snake_case$1);
12222
- preserve(normalizeTo_PascalCase$1);
12223
- preserve(parseKeywords);
12224
- preserve(normalizeTo_SCREAMING_CASE$1);
12223
+ $preserve(capitalize$1);
12224
+ $preserve(decapitalize$1);
12225
+ $preserve(nameToUriPart$1);
12226
+ $preserve(nameToUriParts$1);
12227
+ $preserve(removeDiacritics$1);
12228
+ $preserve(normalizeWhitespaces$1);
12229
+ $preserve(normalizeToKebabCase$1);
12230
+ $preserve(normalizeTo_camelCase$1);
12231
+ $preserve(normalizeTo_snake_case$1);
12232
+ $preserve(normalizeTo_PascalCase$1);
12233
+ $preserve(parseKeywords);
12234
+ $preserve(normalizeTo_SCREAMING_CASE$1);
12225
12235
  //-------[/n12]---
12226
12236
  if (!script.includes('return')) {
12227
12237
  script = `return ${script}`;
@@ -13722,7 +13732,7 @@ async function runInteractiveChatbot(options) {
13722
13732
  previousConversationSummary: conversationSummary,
13723
13733
  userMessage,
13724
13734
  };
13725
- const result = await pipelineExecutor(inputParameters).asPromise();
13735
+ const result = await pipelineExecutor(inputParameters).asPromise({ isCrashedOnError: true });
13726
13736
  console.info(`\n`);
13727
13737
  console.info(spaceTrim((block) => `
13728
13738
 
@@ -17817,7 +17827,18 @@ class OpenAiCompatibleExecutionTools {
17817
17827
  const openAiOptions = { ...this.options };
17818
17828
  delete openAiOptions.isVerbose;
17819
17829
  delete openAiOptions.userId;
17820
- this.client = new OpenAI(openAiOptions);
17830
+ // Enhanced configuration for better ECONNRESET handling
17831
+ const enhancedOptions = {
17832
+ ...openAiOptions,
17833
+ timeout: API_REQUEST_TIMEOUT,
17834
+ maxRetries: CONNECTION_RETRIES_LIMIT,
17835
+ defaultHeaders: {
17836
+ Connection: 'keep-alive',
17837
+ 'Keep-Alive': 'timeout=30, max=100',
17838
+ ...openAiOptions.defaultHeaders,
17839
+ },
17840
+ };
17841
+ this.client = new OpenAI(enhancedOptions);
17821
17842
  }
17822
17843
  return this.client;
17823
17844
  }
@@ -17905,7 +17926,7 @@ class OpenAiCompatibleExecutionTools {
17905
17926
  console.info(colors.bgWhite('rawRequest'), JSON.stringify(rawRequest, null, 4));
17906
17927
  }
17907
17928
  const rawResponse = await this.limiter
17908
- .schedule(() => client.chat.completions.create(rawRequest))
17929
+ .schedule(() => this.makeRequestWithRetry(() => client.chat.completions.create(rawRequest)))
17909
17930
  .catch((error) => {
17910
17931
  assertsError(error);
17911
17932
  if (this.options.isVerbose) {
@@ -17981,7 +18002,7 @@ class OpenAiCompatibleExecutionTools {
17981
18002
  console.info(colors.bgWhite('rawRequest'), JSON.stringify(rawRequest, null, 4));
17982
18003
  }
17983
18004
  const rawResponse = await this.limiter
17984
- .schedule(() => client.completions.create(rawRequest))
18005
+ .schedule(() => this.makeRequestWithRetry(() => client.completions.create(rawRequest)))
17985
18006
  .catch((error) => {
17986
18007
  assertsError(error);
17987
18008
  if (this.options.isVerbose) {
@@ -18045,7 +18066,7 @@ class OpenAiCompatibleExecutionTools {
18045
18066
  console.info(colors.bgWhite('rawRequest'), JSON.stringify(rawRequest, null, 4));
18046
18067
  }
18047
18068
  const rawResponse = await this.limiter
18048
- .schedule(() => client.embeddings.create(rawRequest))
18069
+ .schedule(() => this.makeRequestWithRetry(() => client.embeddings.create(rawRequest)))
18049
18070
  .catch((error) => {
18050
18071
  assertsError(error);
18051
18072
  if (this.options.isVerbose) {
@@ -18103,6 +18124,76 @@ class OpenAiCompatibleExecutionTools {
18103
18124
  }
18104
18125
  return model;
18105
18126
  }
18127
+ // <- Note: [🤖] getDefaultXxxModel
18128
+ /**
18129
+ * Makes a request with retry logic for network errors like ECONNRESET
18130
+ */
18131
+ async makeRequestWithRetry(requestFn) {
18132
+ let lastError;
18133
+ for (let attempt = 1; attempt <= CONNECTION_RETRIES_LIMIT; attempt++) {
18134
+ try {
18135
+ return await requestFn();
18136
+ }
18137
+ catch (error) {
18138
+ assertsError(error);
18139
+ lastError = error;
18140
+ // Check if this is a retryable network error
18141
+ const isRetryableError = this.isRetryableNetworkError(error);
18142
+ if (!isRetryableError || attempt === CONNECTION_RETRIES_LIMIT) {
18143
+ if (this.options.isVerbose) {
18144
+ console.info(colors.bgRed('Final error after retries'), `Attempt ${attempt}/${CONNECTION_RETRIES_LIMIT}:`, error);
18145
+ }
18146
+ throw error;
18147
+ }
18148
+ // Calculate exponential backoff delay
18149
+ const baseDelay = 1000; // 1 second
18150
+ const backoffDelay = baseDelay * Math.pow(2, attempt - 1);
18151
+ const jitterDelay = Math.random() * 500; // Add some randomness
18152
+ const totalDelay = backoffDelay + jitterDelay;
18153
+ if (this.options.isVerbose) {
18154
+ console.info(colors.bgYellow('Retrying request'), `Attempt ${attempt}/${CONNECTION_RETRIES_LIMIT}, waiting ${Math.round(totalDelay)}ms:`, error.message);
18155
+ }
18156
+ // Wait before retrying
18157
+ await new Promise((resolve) => setTimeout(resolve, totalDelay));
18158
+ }
18159
+ }
18160
+ throw lastError;
18161
+ }
18162
+ /**
18163
+ * Determines if an error is retryable (network-related errors)
18164
+ */
18165
+ isRetryableNetworkError(error) {
18166
+ const errorMessage = error.message.toLowerCase();
18167
+ const errorCode = error.code;
18168
+ // Network connection errors that should be retried
18169
+ const retryableErrors = [
18170
+ 'econnreset',
18171
+ 'enotfound',
18172
+ 'econnrefused',
18173
+ 'etimedout',
18174
+ 'socket hang up',
18175
+ 'network error',
18176
+ 'fetch failed',
18177
+ 'connection reset',
18178
+ 'connection refused',
18179
+ 'timeout',
18180
+ ];
18181
+ // Check error message
18182
+ if (retryableErrors.some((retryableError) => errorMessage.includes(retryableError))) {
18183
+ return true;
18184
+ }
18185
+ // Check error code
18186
+ if (errorCode && retryableErrors.includes(errorCode.toLowerCase())) {
18187
+ return true;
18188
+ }
18189
+ // Check for specific HTTP status codes that are retryable
18190
+ const errorWithStatus = error;
18191
+ const httpStatus = errorWithStatus.status || errorWithStatus.statusCode;
18192
+ if (httpStatus && [429, 500, 502, 503, 504].includes(httpStatus)) {
18193
+ return true;
18194
+ }
18195
+ return false;
18196
+ }
18106
18197
  }
18107
18198
  /**
18108
18199
  * TODO: [🛄] Some way how to re-wrap the errors from `OpenAiCompatibleExecutionTools`
@@ -19155,7 +19246,9 @@ class MarkdownScraper {
19155
19246
  },
19156
19247
  });
19157
19248
  const knowledgeContent = await source.asText();
19158
- const result = await prepareKnowledgeFromMarkdownExecutor({ knowledgeContent }).asPromise();
19249
+ const result = await prepareKnowledgeFromMarkdownExecutor({ knowledgeContent }).asPromise({
19250
+ isCrashedOnError: true,
19251
+ });
19159
19252
  const { outputParameters } = result;
19160
19253
  const { knowledgePieces: knowledgePiecesRaw } = outputParameters;
19161
19254
  const knowledgeTextPieces = (knowledgePiecesRaw || '').split('\n---\n');
@@ -19179,12 +19272,16 @@ class MarkdownScraper {
19179
19272
  ];
19180
19273
  */
19181
19274
  try {
19182
- const titleResult = await prepareTitleExecutor({ knowledgePieceContent }).asPromise();
19275
+ const titleResult = await prepareTitleExecutor({ knowledgePieceContent }).asPromise({
19276
+ isCrashedOnError: true,
19277
+ });
19183
19278
  const { title: titleRaw = 'Untitled' } = titleResult.outputParameters;
19184
19279
  title = spaceTrim(titleRaw) /* <- TODO: Maybe do in pipeline */;
19185
19280
  name = titleToName(title);
19186
19281
  // --- Keywords
19187
- const keywordsResult = await prepareKeywordsExecutor({ knowledgePieceContent }).asPromise();
19282
+ const keywordsResult = await prepareKeywordsExecutor({ knowledgePieceContent }).asPromise({
19283
+ isCrashedOnError: true,
19284
+ });
19188
19285
  const { keywords: keywordsRaw = '' } = keywordsResult.outputParameters;
19189
19286
  keywords = (keywordsRaw || '')
19190
19287
  .split(',')