@promptbook/pdf 0.100.0-45 → 0.100.0-46

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.
@@ -11,6 +11,8 @@ import type { BookEditorProps } from '../book-components/BookEditor/BookEditor';
11
11
  import { BookEditor } from '../book-components/BookEditor/BookEditor';
12
12
  import { DEFAULT_BOOK_FONT_CLASS } from '../book-components/BookEditor/config';
13
13
  import { Chat } from '../book-components/Chat/Chat/Chat';
14
+ import type { ChatMessage } from '../book-components/Chat/interfaces/ChatMessage';
15
+ import type { ChatParticipant } from '../book-components/Chat/interfaces/ChatParticipant';
14
16
  export { BOOK_LANGUAGE_VERSION, PROMPTBOOK_ENGINE_VERSION };
15
17
  export type { AvatarChipProps };
16
18
  export { AvatarChip };
@@ -24,3 +26,5 @@ export type { BookEditorProps };
24
26
  export { BookEditor };
25
27
  export { DEFAULT_BOOK_FONT_CLASS };
26
28
  export { Chat };
29
+ export type { ChatMessage };
30
+ export type { ChatParticipant };
@@ -49,6 +49,7 @@ import { DEFAULT_IS_AUTO_INSTALLED } from '../config';
49
49
  import { DEFAULT_TASK_SIMULATED_DURATION_MS } from '../config';
50
50
  import { DEFAULT_GET_PIPELINE_COLLECTION_FUNCTION_NAME } from '../config';
51
51
  import { DEFAULT_MAX_REQUESTS_PER_MINUTE } from '../config';
52
+ import { API_REQUEST_TIMEOUT } from '../config';
52
53
  import { PROMPTBOOK_LOGO_URL } from '../config';
53
54
  import { MODEL_TRUST_LEVELS } from '../constants';
54
55
  import { MODEL_ORDERS } from '../constants';
@@ -212,6 +213,7 @@ export { DEFAULT_IS_AUTO_INSTALLED };
212
213
  export { DEFAULT_TASK_SIMULATED_DURATION_MS };
213
214
  export { DEFAULT_GET_PIPELINE_COLLECTION_FUNCTION_NAME };
214
215
  export { DEFAULT_MAX_REQUESTS_PER_MINUTE };
216
+ export { API_REQUEST_TIMEOUT };
215
217
  export { PROMPTBOOK_LOGO_URL };
216
218
  export { MODEL_TRUST_LEVELS };
217
219
  export { MODEL_ORDERS };
@@ -17,9 +17,7 @@ import type { AvatarProfileProps } from '../book-components/AvatarProfile/Avatar
17
17
  import type { AvatarProfileFromSourceProps } from '../book-components/AvatarProfile/AvatarProfile/AvatarProfileFromSource';
18
18
  import type { BookEditorProps } from '../book-components/BookEditor/BookEditor';
19
19
  import type { ChatMessage } from '../book-components/Chat/interfaces/ChatMessage';
20
- import type { UserChatMessage } from '../book-components/Chat/interfaces/ChatMessage';
21
- import type { PromptbookPersonaChatMessage } from '../book-components/Chat/interfaces/ChatMessage';
22
- import type { CompleteChatMessage } from '../book-components/Chat/interfaces/ChatMessage';
20
+ import type { ChatParticipant } from '../book-components/Chat/interfaces/ChatParticipant';
23
21
  import type { PipelineCollection } from '../collection/PipelineCollection';
24
22
  import type { Command } from '../commands/_common/types/Command';
25
23
  import type { CommandParser } from '../commands/_common/types/CommandParser';
@@ -344,9 +342,7 @@ export type { AvatarProfileProps };
344
342
  export type { AvatarProfileFromSourceProps };
345
343
  export type { BookEditorProps };
346
344
  export type { ChatMessage };
347
- export type { UserChatMessage };
348
- export type { PromptbookPersonaChatMessage };
349
- export type { CompleteChatMessage };
345
+ export type { ChatParticipant };
350
346
  export type { PipelineCollection };
351
347
  export type { Command };
352
348
  export type { CommandParser };
@@ -1,4 +1,4 @@
1
- import { TODO_any } from "../../../_packages/types.index";
1
+ import type { TODO_any } from '../../../utils/organization/TODO_any';
2
2
  /**
3
3
  * Model requirements for an agent
4
4
  *
@@ -1,6 +1,7 @@
1
1
  import type { CSSProperties, ReactNode } from 'react';
2
2
  import type { Promisable } from 'type-fest';
3
3
  import type { ChatMessage } from '../interfaces/ChatMessage';
4
+ import type { ChatParticipant } from '../interfaces/ChatParticipant';
4
5
  /**
5
6
  * @deprecated use `isComplete` instead
6
7
  * @private util of `<Chat />`
@@ -11,11 +12,11 @@ interface ChatProps {
11
12
  * Optional callback to create a new agent from the template.
12
13
  * If provided, renders the [Use this template] button.
13
14
  */
14
- onUseTemplate?: () => void;
15
+ onUseTemplate?(): void;
15
16
  /**
16
17
  * Messages to render - they are rendered as they are
17
18
  */
18
- readonly messages: Array<ChatMessage>;
19
+ readonly messages: ReadonlyArray<ChatMessage>;
19
20
  /**
20
21
  * Called every time the user types or dictated a message
21
22
  */
@@ -38,10 +39,6 @@ interface ChatProps {
38
39
  * The language code to use for voice recognition
39
40
  */
40
41
  readonly voiceLanguage?: string;
41
- /**
42
- * Avatars for each user
43
- */
44
- readonly avatars?: Partial<Record<ChatMessage['from'], string>>;
45
42
  /**
46
43
  * Optional placeholder message for the textarea
47
44
  *
@@ -105,10 +102,7 @@ interface ChatProps {
105
102
  * Optional mapping of participant IDs (message.from) to display metadata for exports.
106
103
  * Keys should match ChatMessage.from values (e.g., 'USER', 'AGENT_{id}', etc.)
107
104
  */
108
- readonly participants?: Record<string, {
109
- name: string;
110
- avatarUrl?: string;
111
- }>;
105
+ readonly participants?: ReadonlyArray<ChatParticipant>;
112
106
  }
113
107
  /**
114
108
  * Renders a chat with messages and input for new messages
@@ -1,30 +1,16 @@
1
- export type ChatMessage = UserChatMessage | PromptbookPersonaChatMessage;
2
- export interface UserChatMessage {
3
- id: string;
4
- date: Date;
5
- from: 'USER';
6
- content: string;
7
- isComplete: boolean;
8
- expectedAnswer?: string;
9
- isVoiceCall?: boolean;
10
- }
11
- export interface PromptbookPersonaChatMessage {
1
+ import type { string_markdown } from '../../../types/typeAliases';
2
+ import type { string_name } from '../../../types/typeAliases';
3
+ /**
4
+ * A message in the chat
5
+ *
6
+ * @public exported from `@promptbook/components`
7
+ */
8
+ export type ChatMessage = {
12
9
  id: string;
13
10
  date: Date;
14
- from: 'PROMPTBOOK_PERSONA';
15
- avatar?: string | {
16
- src: string;
17
- width?: number;
18
- height?: number;
19
- };
20
- content: string;
21
- isComplete: boolean;
11
+ from: string_name;
12
+ content: string_markdown;
13
+ isComplete?: boolean;
22
14
  expectedAnswer?: string;
23
15
  isVoiceCall?: boolean;
24
- }
25
- export interface CompleteChatMessage {
26
- isComplete: true;
27
- }
28
- /**
29
- * TODO: [🧠] ACRY Rename PROMPTBOOK_PERSONA + USER, Teacher, teacher to sth else
30
- */
16
+ };
@@ -0,0 +1,12 @@
1
+ import type { string_name } from '../../../types/typeAliases';
2
+ import type { string_url_image } from '../../../types/typeAliases';
3
+ /**
4
+ * A participant in the chat
5
+ *
6
+ * @public exported from `@promptbook/components`
7
+ */
8
+ export type ChatParticipant = {
9
+ name: string_name;
10
+ avatarUrl?: string_url_image;
11
+ color: string;
12
+ };
@@ -301,6 +301,13 @@ export declare const DEFAULT_GET_PIPELINE_COLLECTION_FUNCTION_NAME = "getPipelin
301
301
  * @public exported from `@promptbook/core`
302
302
  */
303
303
  export declare const DEFAULT_MAX_REQUESTS_PER_MINUTE = 60;
304
+ /**
305
+ * API request timeout in milliseconds
306
+ * Can be overridden via API_REQUEST_TIMEOUT environment variable
307
+ *
308
+ * @public exported from `@promptbook/core`
309
+ */
310
+ export declare const API_REQUEST_TIMEOUT: number;
304
311
  /**
305
312
  * URL of the Promptbook logo
306
313
  *
@@ -110,6 +110,14 @@ export type AbstractTask<TTaskResult extends AbstractTaskResult> = {
110
110
  * Gets a promise that resolves with the task result
111
111
  */
112
112
  asPromise(options?: {
113
+ /**
114
+ * Do the task throws on error
115
+ *
116
+ * - If `true` when error occurs the returned promise will rejects
117
+ * - If `false` the promise will resolve with object with all listed errors and warnings and partial result
118
+ *
119
+ * @default true
120
+ */
113
121
  readonly isCrashedOnError?: boolean;
114
122
  }): Promise<TTaskResult>;
115
123
  /**
@@ -82,6 +82,14 @@ export declare abstract class OpenAiCompatibleExecutionTools implements LlmExecu
82
82
  * Default model for completion variant.
83
83
  */
84
84
  protected abstract getDefaultEmbeddingModel(): AvailableModel;
85
+ /**
86
+ * Makes a request with retry logic for network errors like ECONNRESET
87
+ */
88
+ private makeRequestWithRetry;
89
+ /**
90
+ * Determines if an error is retryable (network-related errors)
91
+ */
92
+ private isRetryableNetworkError;
85
93
  }
86
94
  /**
87
95
  * TODO: [🛄] Some way how to re-wrap the errors from `OpenAiCompatibleExecutionTools`
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ts-node
2
+ export {};
3
+ /**
4
+ * Note: [⚫] Code in this file should never be published in any package
5
+ */
@@ -0,0 +1,21 @@
1
+ import type { really_any } from './really_any';
2
+ /**
3
+ * Does nothing, but preserves the function in the bundle
4
+ * Compiler is tricked into thinking the function is used
5
+ *
6
+ * @param value any function to preserve
7
+ * @returns nothing
8
+ * @private within the repository
9
+ */
10
+ export declare function $preserve(...value: Array<really_any>): void;
11
+ /**
12
+ * DO NOT USE THIS FUNCTION
13
+ * Only purpose of this function is to trick the compiler and javascript engine
14
+ * that `_preserved` array can be used in the future and should not be garbage collected
15
+ *
16
+ * @private internal for `preserve`
17
+ */
18
+ export declare function __DO_NOT_USE_getPreserved(): Array<really_any>;
19
+ /**
20
+ * Note: [💞] Ignore a discrepancy between file name and entity name
21
+ */
@@ -15,7 +15,7 @@ export declare const BOOK_LANGUAGE_VERSION: string_semantic_version;
15
15
  export declare const PROMPTBOOK_ENGINE_VERSION: string_promptbook_version;
16
16
  /**
17
17
  * Represents the version string of the Promptbook engine.
18
- * It follows semantic versioning (e.g., `0.100.0-44`).
18
+ * It follows semantic versioning (e.g., `0.100.0-45`).
19
19
  *
20
20
  * @generated
21
21
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@promptbook/pdf",
3
- "version": "0.100.0-45",
3
+ "version": "0.100.0-46",
4
4
  "description": "Promptbook: Run AI apps in plain human language across multiple models and platforms",
5
5
  "private": false,
6
6
  "sideEffects": false,
@@ -94,14 +94,13 @@
94
94
  "module": "./esm/index.es.js",
95
95
  "typings": "./esm/typings/src/_packages/pdf.index.d.ts",
96
96
  "peerDependencies": {
97
- "@promptbook/core": "0.100.0-45"
97
+ "@promptbook/core": "0.100.0-46"
98
98
  },
99
99
  "dependencies": {
100
100
  "crypto": "1.0.1",
101
101
  "crypto-js": "4.2.0",
102
102
  "markitdown-ts": "0.0.4",
103
103
  "papaparse": "5.4.1",
104
- "prettier": "2.8.1",
105
104
  "rxjs": "7.8.1",
106
105
  "spacetrim": "0.11.59",
107
106
  "waitasecond": "1.11.83"
package/umd/index.umd.js CHANGED
@@ -1,14 +1,15 @@
1
1
  (function (global, factory) {
2
- typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('fs/promises'), require('spacetrim'), require('crypto-js'), require('crypto-js/enc-hex'), require('path'), require('prettier'), require('prettier/parser-html'), require('crypto'), require('rxjs'), require('waitasecond'), require('crypto-js/sha256'), require('mime-types'), require('papaparse')) :
3
- typeof define === 'function' && define.amd ? define(['exports', 'fs/promises', 'spacetrim', 'crypto-js', 'crypto-js/enc-hex', 'path', 'prettier', 'prettier/parser-html', 'crypto', 'rxjs', 'waitasecond', 'crypto-js/sha256', 'mime-types', 'papaparse'], factory) :
4
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global["promptbook-pdf"] = {}, global.promises, global.spaceTrim, global.cryptoJs, global.hexEncoder, global.path, global.prettier, global.parserHtml, global.crypto, global.rxjs, global.waitasecond, global.sha256, global.mimeTypes, global.papaparse));
5
- })(this, (function (exports, promises, spaceTrim, cryptoJs, hexEncoder, path, prettier, parserHtml, crypto, rxjs, waitasecond, sha256, mimeTypes, papaparse) { 'use strict';
2
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('fs/promises'), require('spacetrim'), require('crypto-js'), require('crypto-js/enc-hex'), require('path'), require('prettier/parser-html'), require('prettier/parser-markdown'), require('prettier/standalone'), require('crypto'), require('rxjs'), require('waitasecond'), require('crypto-js/sha256'), require('mime-types'), require('papaparse')) :
3
+ typeof define === 'function' && define.amd ? define(['exports', 'fs/promises', 'spacetrim', 'crypto-js', 'crypto-js/enc-hex', 'path', 'prettier/parser-html', 'prettier/parser-markdown', 'prettier/standalone', 'crypto', 'rxjs', 'waitasecond', 'crypto-js/sha256', 'mime-types', 'papaparse'], factory) :
4
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global["promptbook-pdf"] = {}, global.promises, global.spaceTrim, global.cryptoJs, global.hexEncoder, global.path, global.parserHtml, global.parserMarkdown, global.standalone, global.crypto, global.rxjs, global.waitasecond, global.sha256, global.mimeTypes, global.papaparse));
5
+ })(this, (function (exports, promises, spaceTrim, cryptoJs, hexEncoder, path, parserHtml, parserMarkdown, standalone, crypto, rxjs, waitasecond, sha256, mimeTypes, papaparse) { 'use strict';
6
6
 
7
7
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
8
8
 
9
9
  var spaceTrim__default = /*#__PURE__*/_interopDefaultLegacy(spaceTrim);
10
10
  var hexEncoder__default = /*#__PURE__*/_interopDefaultLegacy(hexEncoder);
11
11
  var parserHtml__default = /*#__PURE__*/_interopDefaultLegacy(parserHtml);
12
+ var parserMarkdown__default = /*#__PURE__*/_interopDefaultLegacy(parserMarkdown);
12
13
  var sha256__default = /*#__PURE__*/_interopDefaultLegacy(sha256);
13
14
 
14
15
  // ⚠️ WARNING: This code has been generated so that any manual changes will be overwritten
@@ -25,7 +26,7 @@
25
26
  * @generated
26
27
  * @see https://github.com/webgptorg/promptbook
27
28
  */
28
- const PROMPTBOOK_ENGINE_VERSION = '0.100.0-45';
29
+ const PROMPTBOOK_ENGINE_VERSION = '0.100.0-46';
29
30
  /**
30
31
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
31
32
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -223,6 +224,13 @@
223
224
  * @public exported from `@promptbook/core`
224
225
  */
225
226
  const DEFAULT_TASK_SIMULATED_DURATION_MS = 5 * 60 * 1000; // 5 minutes
227
+ /**
228
+ * API request timeout in milliseconds
229
+ * Can be overridden via API_REQUEST_TIMEOUT environment variable
230
+ *
231
+ * @public exported from `@promptbook/core`
232
+ */
233
+ parseInt(process.env.API_REQUEST_TIMEOUT || '90000');
226
234
  /**
227
235
  * Indicates whether pipeline logic validation is enabled. When true, the pipeline logic is checked for consistency.
228
236
  *
@@ -1037,9 +1045,9 @@
1037
1045
  */
1038
1046
  function prettifyMarkdown(content) {
1039
1047
  try {
1040
- return prettier.format(content, {
1048
+ return standalone.format(content, {
1041
1049
  parser: 'markdown',
1042
- plugins: [parserHtml__default["default"]],
1050
+ plugins: [parserMarkdown__default["default"], parserHtml__default["default"]],
1043
1051
  // TODO: DRY - make some import or auto-copy of .prettierrc
1044
1052
  endOfLine: 'lf',
1045
1053
  tabWidth: 4,
@@ -3179,7 +3187,7 @@
3179
3187
  const result = await preparePersonaExecutor({
3180
3188
  availableModels /* <- Note: Passing as JSON */,
3181
3189
  personaDescription,
3182
- }).asPromise();
3190
+ }).asPromise({ isCrashedOnError: true });
3183
3191
  const { outputParameters } = result;
3184
3192
  const { modelsRequirements: modelsRequirementsJson } = outputParameters;
3185
3193
  let modelsRequirementsUnchecked = jsonParse(modelsRequirementsJson);
@@ -3943,7 +3951,7 @@
3943
3951
  });
3944
3952
  const result = await prepareTitleExecutor({
3945
3953
  book: sources.map(({ content }) => content).join('\n\n'),
3946
- }).asPromise();
3954
+ }).asPromise({ isCrashedOnError: true });
3947
3955
  const { outputParameters } = result;
3948
3956
  const { title: titleRaw } = outputParameters;
3949
3957
  if (isVerbose) {
@@ -6158,64 +6166,74 @@
6158
6166
  });
6159
6167
  });
6160
6168
  };
6161
- const pipelineExecutor = (inputParameters) => createTask({
6162
- taskType: 'EXECUTION',
6163
- title: pipeline.title,
6164
- taskProcessCallback(updateOngoingResult, updateTldr) {
6165
- return pipelineExecutorWithCallback(inputParameters, async (newOngoingResult) => {
6166
- var _a;
6167
- updateOngoingResult(newOngoingResult);
6168
- // Calculate and update tldr based on pipeline progress
6169
- const cv = newOngoingResult;
6170
- // Calculate progress based on pipeline tasks
6171
- const totalTasks = pipeline.tasks.length;
6172
- let completedTasks = 0;
6173
- let currentTaskName = '';
6174
- // Check execution report for completed tasks
6175
- if ((_a = cv === null || cv === void 0 ? void 0 : cv.executionReport) === null || _a === void 0 ? void 0 : _a.promptExecutions) {
6176
- const executedTaskTitles = new Set(cv.executionReport.promptExecutions.map((execution) => execution.prompt.title));
6177
- // Count completed tasks by matching titles
6178
- const completedTasksByTitle = pipeline.tasks.filter((task) => executedTaskTitles.has(task.title));
6179
- completedTasks = completedTasksByTitle.length;
6180
- // Find current task being executed (first task not yet completed)
6181
- const remainingTasks = pipeline.tasks.filter((task) => !executedTaskTitles.has(task.title));
6182
- if (remainingTasks.length > 0) {
6183
- currentTaskName = remainingTasks[0].name;
6169
+ const pipelineExecutor = (inputParameters) => {
6170
+ const startTime = new Date().getTime();
6171
+ return createTask({
6172
+ taskType: 'EXECUTION',
6173
+ title: pipeline.title,
6174
+ taskProcessCallback(updateOngoingResult, updateTldr) {
6175
+ return pipelineExecutorWithCallback(inputParameters, async (newOngoingResult) => {
6176
+ var _a, _b;
6177
+ updateOngoingResult(newOngoingResult);
6178
+ // Calculate and update tldr based on pipeline progress
6179
+ const cv = newOngoingResult;
6180
+ // Calculate progress based on parameters resolved vs total parameters
6181
+ const totalParameters = pipeline.parameters.filter(p => !p.isInput).length;
6182
+ let resolvedParameters = 0;
6183
+ let currentTaskTitle = '';
6184
+ // Get the resolved parameters from output parameters
6185
+ if (cv === null || cv === void 0 ? void 0 : cv.outputParameters) {
6186
+ // Count how many output parameters have non-empty values
6187
+ resolvedParameters = Object.values(cv.outputParameters).filter(value => value !== undefined && value !== null && String(value).trim() !== '').length;
6184
6188
  }
6185
- }
6186
- // Calculate progress percentage
6187
- let percent = totalTasks > 0 ? completedTasks / totalTasks : 0;
6188
- // Add time-based progress for current task (assuming 5 minutes total)
6189
- if (completedTasks < totalTasks) {
6190
- const elapsedMs = new Date().getTime() - new Date().getTime(); // Will be overridden by actual elapsed time in task
6191
- const totalMs = 5 * 60 * 1000; // 5 minutes
6192
- const timeProgress = Math.min(elapsedMs / totalMs, 1);
6193
- // Add partial progress for current task
6194
- percent += (1 / totalTasks) * timeProgress;
6195
- }
6196
- // Clamp to [0,1]
6197
- percent = Math.min(Math.max(percent, 0), 1);
6198
- // Generate message
6199
- let message = '';
6200
- if (currentTaskName) {
6201
- // Find the task to get its title
6202
- const currentTask = pipeline.tasks.find((task) => task.name === currentTaskName);
6203
- const taskTitle = (currentTask === null || currentTask === void 0 ? void 0 : currentTask.title) || currentTaskName;
6204
- message = `Working on task ${taskTitle}`;
6205
- }
6206
- else if (completedTasks === 0) {
6207
- message = 'Starting pipeline execution';
6208
- }
6209
- else {
6210
- message = `Processing pipeline (${completedTasks}/${totalTasks} tasks completed)`;
6211
- }
6212
- updateTldr({
6213
- percent: percent,
6214
- message,
6189
+ // Try to determine current task from execution report
6190
+ if (((_a = cv === null || cv === void 0 ? void 0 : cv.executionReport) === null || _a === void 0 ? void 0 : _a.promptExecutions) && cv.executionReport.promptExecutions.length > 0) {
6191
+ const lastExecution = cv.executionReport.promptExecutions[cv.executionReport.promptExecutions.length - 1];
6192
+ if ((_b = lastExecution === null || lastExecution === void 0 ? void 0 : lastExecution.prompt) === null || _b === void 0 ? void 0 : _b.title) {
6193
+ currentTaskTitle = lastExecution.prompt.title;
6194
+ }
6195
+ }
6196
+ // Calculate base progress percentage
6197
+ let percent = totalParameters > 0 ? resolvedParameters / totalParameters : 0;
6198
+ // Add time-based progress for current task if we haven't completed all parameters
6199
+ if (resolvedParameters < totalParameters) {
6200
+ const elapsedMs = new Date().getTime() - startTime;
6201
+ const estimatedTotalMs = totalParameters * 30 * 1000; // Estimate 30 seconds per parameter
6202
+ const timeProgress = Math.min(elapsedMs / estimatedTotalMs, 0.9); // Cap at 90% for time-based progress
6203
+ // If we have time progress but no parameter progress, show time progress
6204
+ if (percent === 0 && timeProgress > 0) {
6205
+ percent = Math.min(timeProgress, 0.1); // Show some progress but not more than 10%
6206
+ }
6207
+ else if (percent < 1) {
6208
+ // Add partial progress for current task
6209
+ const taskProgress = totalParameters > 0 ? (1 / totalParameters) * 0.5 : 0; // 50% of task progress
6210
+ percent = Math.min(percent + taskProgress, 0.95); // Cap at 95% until fully complete
6211
+ }
6212
+ }
6213
+ // Clamp to [0,1]
6214
+ percent = Math.min(Math.max(percent, 0), 1);
6215
+ // Generate message
6216
+ let message = '';
6217
+ if (currentTaskTitle) {
6218
+ message = `Executing: ${currentTaskTitle}`;
6219
+ }
6220
+ else if (resolvedParameters === 0) {
6221
+ message = 'Starting pipeline execution';
6222
+ }
6223
+ else if (resolvedParameters < totalParameters) {
6224
+ message = `Processing pipeline (${resolvedParameters}/${totalParameters} parameters resolved)`;
6225
+ }
6226
+ else {
6227
+ message = 'Completing pipeline execution';
6228
+ }
6229
+ updateTldr({
6230
+ percent: percent,
6231
+ message,
6232
+ });
6215
6233
  });
6216
- });
6217
- },
6218
- });
6234
+ },
6235
+ });
6236
+ };
6219
6237
  // <- TODO: Make types such as there is no need to do `as` for `createTask`
6220
6238
  return pipelineExecutor;
6221
6239
  }
@@ -6300,7 +6318,9 @@
6300
6318
  },
6301
6319
  });
6302
6320
  const knowledgeContent = await source.asText();
6303
- const result = await prepareKnowledgeFromMarkdownExecutor({ knowledgeContent }).asPromise();
6321
+ const result = await prepareKnowledgeFromMarkdownExecutor({ knowledgeContent }).asPromise({
6322
+ isCrashedOnError: true,
6323
+ });
6304
6324
  const { outputParameters } = result;
6305
6325
  const { knowledgePieces: knowledgePiecesRaw } = outputParameters;
6306
6326
  const knowledgeTextPieces = (knowledgePiecesRaw || '').split('\n---\n');
@@ -6324,12 +6344,16 @@
6324
6344
  ];
6325
6345
  */
6326
6346
  try {
6327
- const titleResult = await prepareTitleExecutor({ knowledgePieceContent }).asPromise();
6347
+ const titleResult = await prepareTitleExecutor({ knowledgePieceContent }).asPromise({
6348
+ isCrashedOnError: true,
6349
+ });
6328
6350
  const { title: titleRaw = 'Untitled' } = titleResult.outputParameters;
6329
6351
  title = spaceTrim__default["default"](titleRaw) /* <- TODO: Maybe do in pipeline */;
6330
6352
  name = titleToName(title);
6331
6353
  // --- Keywords
6332
- const keywordsResult = await prepareKeywordsExecutor({ knowledgePieceContent }).asPromise();
6354
+ const keywordsResult = await prepareKeywordsExecutor({ knowledgePieceContent }).asPromise({
6355
+ isCrashedOnError: true,
6356
+ });
6333
6357
  const { keywords: keywordsRaw = '' } = keywordsResult.outputParameters;
6334
6358
  keywords = (keywordsRaw || '')
6335
6359
  .split(',')