@promptbook/remote-server 0.86.31 → 0.88.0-10

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.
package/umd/index.umd.js CHANGED
@@ -28,7 +28,7 @@
28
28
  * @generated
29
29
  * @see https://github.com/webgptorg/promptbook
30
30
  */
31
- const PROMPTBOOK_ENGINE_VERSION = '0.86.31';
31
+ const PROMPTBOOK_ENGINE_VERSION = '0.88.0-10';
32
32
  /**
33
33
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
34
34
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -1718,6 +1718,57 @@
1718
1718
  * TODO: Maybe use nanoid instead https://github.com/ai/nanoid
1719
1719
  */
1720
1720
 
1721
+ /**
1722
+ * Function isValidJsonString will tell you if the string is valid JSON or not
1723
+ *
1724
+ * @public exported from `@promptbook/utils`
1725
+ */
1726
+ function isValidJsonString(value /* <- [👨‍⚖️] */) {
1727
+ try {
1728
+ JSON.parse(value);
1729
+ return true;
1730
+ }
1731
+ catch (error) {
1732
+ if (!(error instanceof Error)) {
1733
+ throw error;
1734
+ }
1735
+ if (error.message.includes('Unexpected token')) {
1736
+ return false;
1737
+ }
1738
+ return false;
1739
+ }
1740
+ }
1741
+
1742
+ /**
1743
+ * Recursively converts JSON strings to JSON objects
1744
+
1745
+ * @public exported from `@promptbook/utils`
1746
+ */
1747
+ function jsonStringsToJsons(object) {
1748
+ if (object === null) {
1749
+ return object;
1750
+ }
1751
+ if (Array.isArray(object)) {
1752
+ return object.map(jsonStringsToJsons);
1753
+ }
1754
+ if (typeof object !== 'object') {
1755
+ return object;
1756
+ }
1757
+ const newObject = { ...object };
1758
+ for (const [key, value] of Object.entries(object)) {
1759
+ if (typeof value === 'string' && isValidJsonString(value)) {
1760
+ newObject[key] = JSON.parse(value);
1761
+ }
1762
+ else {
1763
+ newObject[key] = jsonStringsToJsons(value);
1764
+ }
1765
+ }
1766
+ return newObject;
1767
+ }
1768
+ /**
1769
+ * TODO: Type the return type correctly
1770
+ */
1771
+
1721
1772
  /**
1722
1773
  * Deserializes the error object
1723
1774
  *
@@ -1790,21 +1841,43 @@
1790
1841
  function createTask(options) {
1791
1842
  const { taskType, taskProcessCallback } = options;
1792
1843
  const taskId = `${taskType.toLowerCase().substring(0, 4)}-${$randomToken(8 /* <- TODO: To global config + Use Base58 to avoid simmilar char conflicts */)}`;
1793
- const partialResultSubject = new rxjs.BehaviorSubject({});
1844
+ let status = 'RUNNING';
1845
+ const createdAt = new Date();
1846
+ let updatedAt = createdAt;
1847
+ const errors = [];
1848
+ const warnings = [];
1849
+ let currentValue = {};
1850
+ const partialResultSubject = new rxjs.Subject();
1851
+ // <- Note: Not using `BehaviorSubject` because on error we can't access the last value
1794
1852
  const finalResultPromise = /* not await */ taskProcessCallback((newOngoingResult) => {
1853
+ Object.assign(currentValue, newOngoingResult);
1854
+ // <- TODO: assign deep
1795
1855
  partialResultSubject.next(newOngoingResult);
1796
1856
  });
1797
1857
  finalResultPromise
1798
1858
  .catch((error) => {
1859
+ errors.push(error);
1799
1860
  partialResultSubject.error(error);
1800
1861
  })
1801
- .then((value) => {
1802
- if (value) {
1862
+ .then((executionResult) => {
1863
+ if (executionResult) {
1803
1864
  try {
1804
- assertsTaskSuccessful(value);
1805
- partialResultSubject.next(value);
1865
+ updatedAt = new Date();
1866
+ errors.push(...executionResult.errors);
1867
+ warnings.push(...executionResult.warnings);
1868
+ // <- TODO: !!! Only unique errors and warnings should be added (or filtered)
1869
+ // TODO: [🧠] !!! errors, warning, isSuccessful are redundant both in `ExecutionTask` and `ExecutionTask.currentValue`
1870
+ // Also maybe move `ExecutionTask.currentValue.usage` -> `ExecutionTask.usage`
1871
+ // And delete `ExecutionTask.currentValue.preparedPipeline`
1872
+ assertsTaskSuccessful(executionResult);
1873
+ status = 'FINISHED';
1874
+ currentValue = jsonStringsToJsons(executionResult);
1875
+ // <- TODO: [🧠] Is this a good idea to convert JSON strins to JSONs?
1876
+ partialResultSubject.next(executionResult);
1806
1877
  }
1807
1878
  catch (error) {
1879
+ status = 'ERROR';
1880
+ errors.push(error);
1808
1881
  partialResultSubject.error(error);
1809
1882
  }
1810
1883
  }
@@ -1821,12 +1894,33 @@
1821
1894
  return {
1822
1895
  taskType,
1823
1896
  taskId,
1897
+ get status() {
1898
+ return status;
1899
+ // <- Note: [1] Theese must be getters to allow changing the value in the future
1900
+ },
1901
+ get createdAt() {
1902
+ return createdAt;
1903
+ // <- Note: [1]
1904
+ },
1905
+ get updatedAt() {
1906
+ return updatedAt;
1907
+ // <- Note: [1]
1908
+ },
1824
1909
  asPromise,
1825
1910
  asObservable() {
1826
1911
  return partialResultSubject.asObservable();
1827
1912
  },
1913
+ get errors() {
1914
+ return errors;
1915
+ // <- Note: [1]
1916
+ },
1917
+ get warnings() {
1918
+ return warnings;
1919
+ // <- Note: [1]
1920
+ },
1828
1921
  get currentValue() {
1829
- return partialResultSubject.value;
1922
+ return currentValue;
1923
+ // <- Note: [1]
1830
1924
  },
1831
1925
  };
1832
1926
  }
@@ -1901,27 +1995,6 @@
1901
1995
  * TODO: [🍏] Implement for MacOs
1902
1996
  */
1903
1997
 
1904
- /**
1905
- * Function isValidJsonString will tell you if the string is valid JSON or not
1906
- *
1907
- * @public exported from `@promptbook/utils`
1908
- */
1909
- function isValidJsonString(value /* <- [👨‍⚖️] */) {
1910
- try {
1911
- JSON.parse(value);
1912
- return true;
1913
- }
1914
- catch (error) {
1915
- if (!(error instanceof Error)) {
1916
- throw error;
1917
- }
1918
- if (error.message.includes('Unexpected token')) {
1919
- return false;
1920
- }
1921
- return false;
1922
- }
1923
- }
1924
-
1925
1998
  /**
1926
1999
  * Function `validatePipelineString` will validate the if the string is a valid pipeline string
1927
2000
  * It does not check if the string is fully logically correct, but if it is a string that can be a pipeline string or the string looks completely different.
@@ -3969,7 +4042,7 @@
3969
4042
  * @param script from which to extract the variables
3970
4043
  * @returns the list of variable names
3971
4044
  * @throws {ParseError} if the script is invalid
3972
- * @public exported from `@promptbook/execute-javascript`
4045
+ * @public exported from `@promptbook/javascript`
3973
4046
  */
3974
4047
  function extractVariablesFromJavascript(script) {
3975
4048
  const variables = new Set();
@@ -5050,7 +5123,7 @@
5050
5123
  Last result:
5051
5124
  ${block($ongoingTaskResult.$resultString === null
5052
5125
  ? 'null'
5053
- : $ongoingTaskResult.$resultString
5126
+ : spaceTrim.spaceTrim($ongoingTaskResult.$resultString)
5054
5127
  .split('\n')
5055
5128
  .map((line) => `> ${line}`)
5056
5129
  .join('\n'))}
@@ -5943,6 +6016,623 @@
5943
6016
  * Note: [🟢] Code in this file should never be never released in packages that could be imported into browser environment
5944
6017
  */
5945
6018
 
6019
+ /**
6020
+ * @@@
6021
+ *
6022
+ * @param text @@@
6023
+ * @param _isFirstLetterCapital @@@
6024
+ * @returns @@@
6025
+ * @example 'helloWorld'
6026
+ * @example 'iLovePromptbook'
6027
+ * @public exported from `@promptbook/utils`
6028
+ */
6029
+ function normalizeTo_camelCase(text, _isFirstLetterCapital = false) {
6030
+ let charType;
6031
+ let lastCharType = null;
6032
+ let normalizedName = '';
6033
+ for (const char of text) {
6034
+ let normalizedChar;
6035
+ if (/^[a-z]$/.test(char)) {
6036
+ charType = 'LOWERCASE';
6037
+ normalizedChar = char;
6038
+ }
6039
+ else if (/^[A-Z]$/.test(char)) {
6040
+ charType = 'UPPERCASE';
6041
+ normalizedChar = char.toLowerCase();
6042
+ }
6043
+ else if (/^[0-9]$/.test(char)) {
6044
+ charType = 'NUMBER';
6045
+ normalizedChar = char;
6046
+ }
6047
+ else {
6048
+ charType = 'OTHER';
6049
+ normalizedChar = '';
6050
+ }
6051
+ if (!lastCharType) {
6052
+ if (_isFirstLetterCapital) {
6053
+ normalizedChar = normalizedChar.toUpperCase(); //TODO: DRY
6054
+ }
6055
+ }
6056
+ else if (charType !== lastCharType &&
6057
+ !(charType === 'LOWERCASE' && lastCharType === 'UPPERCASE') &&
6058
+ !(lastCharType === 'NUMBER') &&
6059
+ !(charType === 'NUMBER')) {
6060
+ normalizedChar = normalizedChar.toUpperCase(); //TODO: [🌺] DRY
6061
+ }
6062
+ normalizedName += normalizedChar;
6063
+ lastCharType = charType;
6064
+ }
6065
+ return normalizedName;
6066
+ }
6067
+ /**
6068
+ * TODO: [🌺] Use some intermediate util splitWords
6069
+ */
6070
+
6071
+ /**
6072
+ * Detects if the code is running in a browser environment in main thread (Not in a web worker)
6073
+ *
6074
+ * Note: `$` is used to indicate that this function is not a pure function - it looks at the global object to determine the environment
6075
+ *
6076
+ * @public exported from `@promptbook/utils`
6077
+ */
6078
+ new Function(`
6079
+ try {
6080
+ return this === window;
6081
+ } catch (e) {
6082
+ return false;
6083
+ }
6084
+ `);
6085
+ /**
6086
+ * TODO: [🎺]
6087
+ */
6088
+
6089
+ /**
6090
+ * Detects if the code is running in jest environment
6091
+ *
6092
+ * Note: `$` is used to indicate that this function is not a pure function - it looks at the global object to determine the environment
6093
+ *
6094
+ * @public exported from `@promptbook/utils`
6095
+ */
6096
+ new Function(`
6097
+ try {
6098
+ return process.env.JEST_WORKER_ID !== undefined;
6099
+ } catch (e) {
6100
+ return false;
6101
+ }
6102
+ `);
6103
+ /**
6104
+ * TODO: [🎺]
6105
+ */
6106
+
6107
+ /**
6108
+ * Detects if the code is running in a web worker
6109
+ *
6110
+ * Note: `$` is used to indicate that this function is not a pure function - it looks at the global object to determine the environment
6111
+ *
6112
+ * @public exported from `@promptbook/utils`
6113
+ */
6114
+ new Function(`
6115
+ try {
6116
+ if (typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope) {
6117
+ return true;
6118
+ } else {
6119
+ return false;
6120
+ }
6121
+ } catch (e) {
6122
+ return false;
6123
+ }
6124
+ `);
6125
+ /**
6126
+ * TODO: [🎺]
6127
+ */
6128
+
6129
+ /**
6130
+ * Makes first letter of a string uppercase
6131
+ *
6132
+ * @public exported from `@promptbook/utils`
6133
+ */
6134
+ function decapitalize(word) {
6135
+ return word.substring(0, 1).toLowerCase() + word.substring(1);
6136
+ }
6137
+
6138
+ /**
6139
+ * Parses keywords from a string
6140
+ *
6141
+ * @param {string} input
6142
+ * @returns {Set} of keywords without diacritics in lowercase
6143
+ * @public exported from `@promptbook/utils`
6144
+ */
6145
+ function parseKeywordsFromString(input) {
6146
+ const keywords = normalizeTo_SCREAMING_CASE(removeDiacritics(input))
6147
+ .toLowerCase()
6148
+ .split(/[^a-z0-9]+/gs)
6149
+ .filter((value) => value);
6150
+ return new Set(keywords);
6151
+ }
6152
+
6153
+ /**
6154
+ * @@@
6155
+ *
6156
+ * @param name @@@
6157
+ * @returns @@@
6158
+ * @example @@@
6159
+ * @public exported from `@promptbook/utils`
6160
+ */
6161
+ function nameToUriPart(name) {
6162
+ let uriPart = name;
6163
+ uriPart = uriPart.toLowerCase();
6164
+ uriPart = removeDiacritics(uriPart);
6165
+ uriPart = uriPart.replace(/[^a-zA-Z0-9]+/g, '-');
6166
+ uriPart = uriPart.replace(/^-+/, '');
6167
+ uriPart = uriPart.replace(/-+$/, '');
6168
+ return uriPart;
6169
+ }
6170
+
6171
+ /**
6172
+ * @@@
6173
+ *
6174
+ * @param name @@@
6175
+ * @returns @@@
6176
+ * @example @@@
6177
+ * @public exported from `@promptbook/utils`
6178
+ */
6179
+ function nameToUriParts(name) {
6180
+ return nameToUriPart(name)
6181
+ .split('-')
6182
+ .filter((value) => value !== '');
6183
+ }
6184
+
6185
+ /**
6186
+ *
6187
+ * @param text @public exported from `@promptbook/utils`
6188
+ * @returns
6189
+ * @example 'HelloWorld'
6190
+ * @example 'ILovePromptbook'
6191
+ * @public exported from `@promptbook/utils`
6192
+ */
6193
+ function normalizeTo_PascalCase(text) {
6194
+ return normalizeTo_camelCase(text, true);
6195
+ }
6196
+
6197
+ /**
6198
+ * Take every whitespace (space, new line, tab) and replace it with a single space
6199
+ *
6200
+ * @public exported from `@promptbook/utils`
6201
+ */
6202
+ function normalizeWhitespaces(sentence) {
6203
+ return sentence.replace(/\s+/gs, ' ').trim();
6204
+ }
6205
+
6206
+ /**
6207
+ * Removes quotes from a string
6208
+ *
6209
+ * Tip: This is very usefull for post-processing of the result of the LLM model
6210
+ * Note: This function removes only the same quotes from the beginning and the end of the string
6211
+ * Note: There are two simmilar functions:
6212
+ * - `removeQuotes` which removes only bounding quotes
6213
+ * - `unwrapResult` which removes whole introduce sentence
6214
+ *
6215
+ * @param text optionally quoted text
6216
+ * @returns text without quotes
6217
+ * @public exported from `@promptbook/utils`
6218
+ */
6219
+ function removeQuotes(text) {
6220
+ if (text.startsWith('"') && text.endsWith('"')) {
6221
+ return text.slice(1, -1);
6222
+ }
6223
+ if (text.startsWith('\'') && text.endsWith('\'')) {
6224
+ return text.slice(1, -1);
6225
+ }
6226
+ return text;
6227
+ }
6228
+
6229
+ /**
6230
+ * Function trimCodeBlock will trim starting and ending code block from the string if it is present.
6231
+ *
6232
+ * Note: This is usefull for post-processing of the result of the chat LLM model
6233
+ * when the model wraps the result in the (markdown) code block.
6234
+ *
6235
+ * @public exported from `@promptbook/utils`
6236
+ */
6237
+ function trimCodeBlock(value) {
6238
+ value = spaceTrim.spaceTrim(value);
6239
+ if (!/^```[a-z]*(.*)```$/is.test(value)) {
6240
+ return value;
6241
+ }
6242
+ value = value.replace(/^```[a-z]*/i, '');
6243
+ value = value.replace(/```$/i, '');
6244
+ value = spaceTrim.spaceTrim(value);
6245
+ return value;
6246
+ }
6247
+
6248
+ /**
6249
+ * Function trimEndOfCodeBlock will remove ending code block from the string if it is present.
6250
+ *
6251
+ * Note: This is usefull for post-processing of the result of the completion LLM model
6252
+ * if you want to start code block in the prompt but you don't want to end it in the result.
6253
+ *
6254
+ * @public exported from `@promptbook/utils`
6255
+ */
6256
+ function trimEndOfCodeBlock(value) {
6257
+ value = spaceTrim.spaceTrim(value);
6258
+ value = value.replace(/```$/g, '');
6259
+ value = spaceTrim.spaceTrim(value);
6260
+ return value;
6261
+ }
6262
+
6263
+ /**
6264
+ * Removes quotes and optional introduce text from a string
6265
+ *
6266
+ * Tip: This is very usefull for post-processing of the result of the LLM model
6267
+ * Note: This function trims the text and removes whole introduce sentence if it is present
6268
+ * Note: There are two simmilar functions:
6269
+ * - `removeQuotes` which removes only bounding quotes
6270
+ * - `unwrapResult` which removes whole introduce sentence
6271
+ *
6272
+ * @param text optionally quoted text
6273
+ * @returns text without quotes
6274
+ * @public exported from `@promptbook/utils`
6275
+ */
6276
+ function unwrapResult(text, options) {
6277
+ const { isTrimmed = true, isIntroduceSentenceRemoved = true } = options || {};
6278
+ let trimmedText = text;
6279
+ // Remove leading and trailing spaces and newlines
6280
+ if (isTrimmed) {
6281
+ trimmedText = spaceTrim.spaceTrim(trimmedText);
6282
+ }
6283
+ let processedText = trimmedText;
6284
+ if (isIntroduceSentenceRemoved) {
6285
+ const introduceSentenceRegex = /^[a-zěščřžýáíéúů:\s]*:\s*/i;
6286
+ if (introduceSentenceRegex.test(text)) {
6287
+ // Remove the introduce sentence and quotes by replacing it with an empty string
6288
+ processedText = processedText.replace(introduceSentenceRegex, '');
6289
+ }
6290
+ processedText = spaceTrim.spaceTrim(processedText);
6291
+ }
6292
+ if (processedText.length < 3) {
6293
+ return trimmedText;
6294
+ }
6295
+ if (processedText.includes('\n')) {
6296
+ return trimmedText;
6297
+ }
6298
+ // Remove the quotes by extracting the substring without the first and last characters
6299
+ const unquotedText = processedText.slice(1, -1);
6300
+ // Check if the text starts and ends with quotes
6301
+ if ([
6302
+ ['"', '"'],
6303
+ ["'", "'"],
6304
+ ['`', '`'],
6305
+ ['*', '*'],
6306
+ ['_', '_'],
6307
+ ['„', '“'],
6308
+ ['«', '»'] /* <- QUOTES to config */,
6309
+ ].some(([startQuote, endQuote]) => {
6310
+ if (!processedText.startsWith(startQuote)) {
6311
+ return false;
6312
+ }
6313
+ if (!processedText.endsWith(endQuote)) {
6314
+ return false;
6315
+ }
6316
+ if (unquotedText.includes(startQuote) && !unquotedText.includes(endQuote)) {
6317
+ return false;
6318
+ }
6319
+ if (!unquotedText.includes(startQuote) && unquotedText.includes(endQuote)) {
6320
+ return false;
6321
+ }
6322
+ return true;
6323
+ })) {
6324
+ return unwrapResult(unquotedText, { isTrimmed: false, isIntroduceSentenceRemoved: false });
6325
+ }
6326
+ else {
6327
+ return processedText;
6328
+ }
6329
+ }
6330
+ /**
6331
+ * TODO: [🧠] Should this also unwrap the (parenthesis)
6332
+ */
6333
+
6334
+ /**
6335
+ * Extracts exactly ONE code block from markdown.
6336
+ *
6337
+ * - When there are multiple or no code blocks the function throws a `ParseError`
6338
+ *
6339
+ * Note: There are multiple simmilar function:
6340
+ * - `extractBlock` just extracts the content of the code block which is also used as build-in function for postprocessing
6341
+ * - `extractJsonBlock` extracts exactly one valid JSON code block
6342
+ * - `extractOneBlockFromMarkdown` extracts exactly one code block with language of the code block
6343
+ * - `extractAllBlocksFromMarkdown` extracts all code blocks with language of the code block
6344
+ *
6345
+ * @param markdown any valid markdown
6346
+ * @returns code block with language and content
6347
+ * @public exported from `@promptbook/markdown-utils`
6348
+ * @throws {ParseError} if there is not exactly one code block in the markdown
6349
+ */
6350
+ function extractOneBlockFromMarkdown(markdown) {
6351
+ const codeBlocks = extractAllBlocksFromMarkdown(markdown);
6352
+ if (codeBlocks.length !== 1) {
6353
+ throw new ParseError(spaceTrim__default["default"]((block) => `
6354
+ There should be exactly 1 code block in task section, found ${codeBlocks.length} code blocks
6355
+
6356
+ ${block(codeBlocks.map((block, i) => `Block ${i + 1}:\n${block.content}`).join('\n\n\n'))}
6357
+ `));
6358
+ }
6359
+ return codeBlocks[0];
6360
+ }
6361
+ /***
6362
+ * TODO: [🍓][🌻] Decide of this is internal utility, external util OR validator/postprocessor
6363
+ */
6364
+
6365
+ /**
6366
+ * Extracts code block from markdown.
6367
+ *
6368
+ * - When there are multiple or no code blocks the function throws a `ParseError`
6369
+ *
6370
+ * Note: There are multiple simmilar function:
6371
+ * - `extractBlock` just extracts the content of the code block which is also used as build-in function for postprocessing
6372
+ * - `extractJsonBlock` extracts exactly one valid JSON code block
6373
+ * - `extractOneBlockFromMarkdown` extracts exactly one code block with language of the code block
6374
+ * - `extractAllBlocksFromMarkdown` extracts all code blocks with language of the code block
6375
+ *
6376
+ * @public exported from `@promptbook/markdown-utils`
6377
+ * @throws {ParseError} if there is not exactly one code block in the markdown
6378
+ */
6379
+ function extractBlock(markdown) {
6380
+ const { content } = extractOneBlockFromMarkdown(markdown);
6381
+ return content;
6382
+ }
6383
+
6384
+ /**
6385
+ * Does nothing, but preserves the function in the bundle
6386
+ * Compiler is tricked into thinking the function is used
6387
+ *
6388
+ * @param value any function to preserve
6389
+ * @returns nothing
6390
+ * @private internal function of `JavascriptExecutionTools` and `JavascriptEvalExecutionTools`
6391
+ */
6392
+ function preserve(func) {
6393
+ // Note: NOT calling the function
6394
+ (async () => {
6395
+ // TODO: [💩] Change to `await forEver` or something better
6396
+ await waitasecond.forTime(100000000);
6397
+ // [1]
6398
+ try {
6399
+ await func();
6400
+ }
6401
+ finally {
6402
+ // do nothing
6403
+ }
6404
+ })();
6405
+ }
6406
+ /**
6407
+ * TODO: Probbably remove in favour of `keepImported`
6408
+ * TODO: [1] This maybe does memory leak
6409
+ */
6410
+
6411
+ // Note: [💎]
6412
+ /**
6413
+ * ScriptExecutionTools for JavaScript implemented via eval
6414
+ *
6415
+ * Warning: It is used for testing and mocking
6416
+ * **NOT intended to use in the production** due to its unsafe nature, use `JavascriptExecutionTools` instead.
6417
+ *
6418
+ * @public exported from `@promptbook/javascript`
6419
+ */
6420
+ class JavascriptEvalExecutionTools {
6421
+ constructor(options) {
6422
+ this.options = options || {};
6423
+ }
6424
+ /**
6425
+ * Executes a JavaScript
6426
+ */
6427
+ async execute(options) {
6428
+ const { scriptLanguage, parameters } = options;
6429
+ let { script } = options;
6430
+ if (scriptLanguage !== 'javascript') {
6431
+ throw new PipelineExecutionError(`Script language ${scriptLanguage} not supported to be executed by JavascriptEvalExecutionTools`);
6432
+ }
6433
+ // Note: [💎]
6434
+ // Note: Using direct eval, following variables are in same scope as eval call so they are accessible from inside the evaluated script:
6435
+ const spaceTrim = (_) => spaceTrim__default["default"](_);
6436
+ preserve(spaceTrim);
6437
+ const removeQuotes$1 = removeQuotes;
6438
+ preserve(removeQuotes$1);
6439
+ const unwrapResult$1 = unwrapResult;
6440
+ preserve(unwrapResult$1);
6441
+ const trimEndOfCodeBlock$1 = trimEndOfCodeBlock;
6442
+ preserve(trimEndOfCodeBlock$1);
6443
+ const trimCodeBlock$1 = trimCodeBlock;
6444
+ preserve(trimCodeBlock$1);
6445
+ // TODO: DRY [🍯]
6446
+ const trim = (str) => str.trim();
6447
+ preserve(trim);
6448
+ // TODO: DRY [🍯]
6449
+ const reverse = (str) => str.split('').reverse().join('');
6450
+ preserve(reverse);
6451
+ const removeEmojis$1 = removeEmojis;
6452
+ preserve(removeEmojis$1);
6453
+ const prettifyMarkdown$1 = prettifyMarkdown;
6454
+ preserve(prettifyMarkdown$1);
6455
+ //-------[n12:]---
6456
+ const capitalize$1 = capitalize;
6457
+ const decapitalize$1 = decapitalize;
6458
+ const nameToUriPart$1 = nameToUriPart;
6459
+ const nameToUriParts$1 = nameToUriParts;
6460
+ const removeDiacritics$1 = removeDiacritics;
6461
+ const normalizeWhitespaces$1 = normalizeWhitespaces;
6462
+ const normalizeToKebabCase$1 = normalizeToKebabCase;
6463
+ const normalizeTo_camelCase$1 = normalizeTo_camelCase;
6464
+ const normalizeTo_snake_case$1 = normalizeTo_snake_case;
6465
+ const normalizeTo_PascalCase$1 = normalizeTo_PascalCase;
6466
+ const parseKeywords = (input) =>
6467
+ // TODO: DRY [🍯]
6468
+ Array.from(parseKeywordsFromString(input)).join(', '); /* <- TODO: [🧠] What is the best format comma list, bullet list,...? */
6469
+ const normalizeTo_SCREAMING_CASE$1 = normalizeTo_SCREAMING_CASE;
6470
+ preserve(capitalize$1);
6471
+ preserve(decapitalize$1);
6472
+ preserve(nameToUriPart$1);
6473
+ preserve(nameToUriParts$1);
6474
+ preserve(removeDiacritics$1);
6475
+ preserve(normalizeWhitespaces$1);
6476
+ preserve(normalizeToKebabCase$1);
6477
+ preserve(normalizeTo_camelCase$1);
6478
+ preserve(normalizeTo_snake_case$1);
6479
+ preserve(normalizeTo_PascalCase$1);
6480
+ preserve(parseKeywords);
6481
+ preserve(normalizeTo_SCREAMING_CASE$1);
6482
+ //-------[/n12]---
6483
+ if (!script.includes('return')) {
6484
+ script = `return ${script}`;
6485
+ }
6486
+ // TODO: DRY [🍯]
6487
+ const buildinFunctions = {
6488
+ // TODO: [🍯] DRY all these functions across the file
6489
+ spaceTrim,
6490
+ removeQuotes: removeQuotes$1,
6491
+ unwrapResult: unwrapResult$1,
6492
+ trimEndOfCodeBlock: trimEndOfCodeBlock$1,
6493
+ trimCodeBlock: trimCodeBlock$1,
6494
+ trim,
6495
+ reverse,
6496
+ removeEmojis: removeEmojis$1,
6497
+ prettifyMarkdown: prettifyMarkdown$1,
6498
+ capitalize: capitalize$1,
6499
+ decapitalize: decapitalize$1,
6500
+ nameToUriPart: nameToUriPart$1,
6501
+ nameToUriParts: nameToUriParts$1,
6502
+ removeDiacritics: removeDiacritics$1,
6503
+ normalizeWhitespaces: normalizeWhitespaces$1,
6504
+ normalizeToKebabCase: normalizeToKebabCase$1,
6505
+ normalizeTo_camelCase: normalizeTo_camelCase$1,
6506
+ normalizeTo_snake_case: normalizeTo_snake_case$1,
6507
+ normalizeTo_PascalCase: normalizeTo_PascalCase$1,
6508
+ parseKeywords,
6509
+ normalizeTo_SCREAMING_CASE: normalizeTo_SCREAMING_CASE$1,
6510
+ extractBlock, // <- [🍓] Remove balast in all other functions, use this one as example
6511
+ };
6512
+ const buildinFunctionsStatement = Object.keys(buildinFunctions)
6513
+ .map((functionName) =>
6514
+ // Note: Custom functions are exposed to the current scope as variables
6515
+ `const ${functionName} = buildinFunctions.${functionName};`)
6516
+ .join('\n');
6517
+ // TODO: DRY [🍯]
6518
+ const customFunctions = this.options.functions || {};
6519
+ const customFunctionsStatement = Object.keys(customFunctions)
6520
+ .map((functionName) =>
6521
+ // Note: Custom functions are exposed to the current scope as variables
6522
+ `const ${functionName} = customFunctions.${functionName};`)
6523
+ .join('\n');
6524
+ // script = templateParameters(script, parameters);
6525
+ // <- TODO: [🧠][🥳] Should be this is one of two variants how to use parameters in script
6526
+ const statementToEvaluate = spaceTrim__default["default"]((block) => `
6527
+
6528
+ // Build-in functions:
6529
+ ${block(buildinFunctionsStatement)}
6530
+
6531
+ // Custom functions:
6532
+ ${block(customFunctionsStatement || '// -- No custom functions --')}
6533
+
6534
+ // The script:
6535
+ ${block(Object.entries(parameters)
6536
+ .map(([key, value]) => `const ${key} = ${JSON.stringify(value)};`)
6537
+ .join('\n'))}
6538
+ (()=>{ ${script} })()
6539
+ `);
6540
+ if (this.options.isVerbose) {
6541
+ console.info(spaceTrim__default["default"]((block) => `
6542
+ 🚀 Evaluating ${scriptLanguage} script:
6543
+
6544
+ ${block(statementToEvaluate)}`));
6545
+ }
6546
+ let result;
6547
+ try {
6548
+ result = await eval(statementToEvaluate);
6549
+ if (typeof result !== 'string') {
6550
+ throw new PipelineExecutionError(`Script must return a string, but returned ${valueToString(result)}`);
6551
+ }
6552
+ }
6553
+ catch (error) {
6554
+ if (!(error instanceof Error)) {
6555
+ throw error;
6556
+ }
6557
+ if (error instanceof ReferenceError) {
6558
+ const undefinedName = error.message.split(' ')[0];
6559
+ /*
6560
+ Note: Remapping error
6561
+ From: [PipelineUrlError: thing is not defined],
6562
+ To: [PipelineExecutionError: Parameter `{thing}` is not defined],
6563
+ */
6564
+ if (!statementToEvaluate.includes(undefinedName + '(')) {
6565
+ throw new PipelineExecutionError(spaceTrim__default["default"]((block) => `
6566
+
6567
+ Parameter \`{${undefinedName}}\` is not defined
6568
+
6569
+ This happen during evaluation of the javascript, which has access to the following parameters as javascript variables:
6570
+
6571
+ ${block(Object.keys(parameters)
6572
+ .map((key) => ` - ${key}\n`)
6573
+ .join(''))}
6574
+
6575
+ The script is:
6576
+ \`\`\`javascript
6577
+ ${block(script)}
6578
+ \`\`\`
6579
+
6580
+ Original error message:
6581
+ ${block(error.message)}
6582
+
6583
+
6584
+ `));
6585
+ }
6586
+ else {
6587
+ throw new PipelineExecutionError(spaceTrim__default["default"]((block) => `
6588
+ Function ${undefinedName}() is not defined
6589
+
6590
+ - Make sure that the function is one of built-in functions
6591
+ - Or you have to defined the function during construction of JavascriptEvalExecutionTools
6592
+
6593
+ Original error message:
6594
+ ${block(error.message)}
6595
+
6596
+ `));
6597
+ }
6598
+ }
6599
+ throw error;
6600
+ }
6601
+ if (typeof result !== 'string') {
6602
+ throw new PipelineExecutionError(`Script must return a string, but ${valueToString(result)}`);
6603
+ }
6604
+ return result;
6605
+ }
6606
+ }
6607
+ /**
6608
+ * TODO: Put predefined functions (like removeQuotes, spaceTrim, etc.) into annotation OR pass into constructor
6609
+ * TODO: [🧠][💙] Distinct between options passed into ExecutionTools and to ExecutionTools.execute
6610
+ */
6611
+
6612
+ /**
6613
+ * Placeholder for better implementation of JavascriptExecutionTools - some propper sandboxing
6614
+ *
6615
+ * @alias JavascriptExecutionTools
6616
+ * @public exported from `@promptbook/javascript`
6617
+ */
6618
+ const JavascriptExecutionTools = JavascriptEvalExecutionTools;
6619
+
6620
+ /**
6621
+ * Provides script execution tools
6622
+ *
6623
+ * @public exported from `@promptbook/node`
6624
+ */
6625
+ async function $provideScriptingForNode(options) {
6626
+ if (!$isRunningInNode()) {
6627
+ throw new EnvironmentMismatchError('Function `$provideScriptingForNode` works only in Node.js environment');
6628
+ }
6629
+ // TODO: [🔱] Do here auto-installation
6630
+ return [new JavascriptExecutionTools(options)];
6631
+ }
6632
+ /**
6633
+ * Note: [🟢] Code in this file should never be never released in packages that could be imported into browser environment
6634
+ */
6635
+
5946
6636
  /**
5947
6637
  * Remote server is a proxy server that uses its execution tools internally and exposes the executor interface externally.
5948
6638
  *
@@ -6014,7 +6704,7 @@
6014
6704
  llm,
6015
6705
  fs,
6016
6706
  scrapers: await $provideScrapersForNode({ fs, llm, executables }),
6017
- // TODO: Allow when `JavascriptExecutionTools` more secure *(without eval)*> script: [new JavascriptExecutionTools()],
6707
+ script: await $provideScriptingForNode({}),
6018
6708
  };
6019
6709
  return tools;
6020
6710
  }
@@ -6025,6 +6715,7 @@
6025
6715
  next();
6026
6716
  });
6027
6717
  const runningExecutionTasks = [];
6718
+ // <- TODO: [🤬] Identify the users
6028
6719
  // TODO: [🧠] Do here some garbage collection of finished tasks
6029
6720
  app.get(['/', rootPath], async (request, response) => {
6030
6721
  var _a;
@@ -6119,23 +6810,60 @@
6119
6810
  .send({ error: serializeError(error) });
6120
6811
  }
6121
6812
  });
6813
+ function exportExecutionTask(executionTask, isFull) {
6814
+ // <- TODO: [🧠] This should be maybe method of `ExecutionTask` itself
6815
+ const { taskType, taskId, status, errors, warnings, createdAt, updatedAt, currentValue } = executionTask;
6816
+ if (isFull) {
6817
+ return {
6818
+ nonce: '✨',
6819
+ taskId,
6820
+ taskType,
6821
+ status,
6822
+ errors: errors.map(serializeError),
6823
+ warnings: warnings.map(serializeError),
6824
+ createdAt,
6825
+ updatedAt,
6826
+ currentValue,
6827
+ };
6828
+ }
6829
+ else {
6830
+ return {
6831
+ nonce: '✨',
6832
+ taskId,
6833
+ taskType,
6834
+ status,
6835
+ createdAt,
6836
+ updatedAt,
6837
+ };
6838
+ }
6839
+ }
6122
6840
  app.get(`${rootPath}/executions`, async (request, response) => {
6123
- response.send(runningExecutionTasks);
6841
+ response.send(runningExecutionTasks.map((runningExecutionTask) => exportExecutionTask(runningExecutionTask, false)));
6842
+ });
6843
+ app.get(`${rootPath}/executions/last`, async (request, response) => {
6844
+ // TODO: [🤬] Filter only for user
6845
+ if (runningExecutionTasks.length === 0) {
6846
+ response.status(404).send('No execution tasks found');
6847
+ return;
6848
+ }
6849
+ const lastExecutionTask = runningExecutionTasks[runningExecutionTasks.length - 1];
6850
+ response.send(exportExecutionTask(lastExecutionTask, true));
6124
6851
  });
6125
6852
  app.get(`${rootPath}/executions/:taskId`, async (request, response) => {
6126
6853
  const { taskId } = request.params;
6127
- const execution = runningExecutionTasks.find((executionTask) => executionTask.taskId === taskId);
6128
- if (execution === undefined) {
6854
+ // TODO: [🤬] Filter only for user
6855
+ const executionTask = runningExecutionTasks.find((executionTask) => executionTask.taskId === taskId);
6856
+ if (executionTask === undefined) {
6129
6857
  response
6130
6858
  .status(404)
6131
6859
  .send(`Execution "${taskId}" not found`);
6132
6860
  return;
6133
6861
  }
6134
- response.send(execution.currentValue);
6862
+ response.send(exportExecutionTask(executionTask, true));
6135
6863
  });
6136
6864
  app.post(`${rootPath}/executions/new`, async (request, response) => {
6137
6865
  try {
6138
- const { inputParameters, identification } = request.body;
6866
+ const { inputParameters, identification /* <- [🤬] */ } = request.body;
6139
6867
  const pipelineUrl = request.body.pipelineUrl || request.body.book;
6140
6868
  // TODO: [🧠] Check `pipelineUrl` and `inputParameters` here or it should be responsibility of `collection.getPipelineByUrl` and `pipelineExecutor`
6141
6869
  const pipeline = await (collection === null || collection === void 0 ? void 0 : collection.getPipelineByUrl(pipelineUrl));