@promptbook/remote-server 0.86.31 → 0.88.0-1

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/esm/index.es.js CHANGED
@@ -31,7 +31,7 @@ const BOOK_LANGUAGE_VERSION = '1.0.0';
31
31
  * @generated
32
32
  * @see https://github.com/webgptorg/promptbook
33
33
  */
34
- const PROMPTBOOK_ENGINE_VERSION = '0.86.31';
34
+ const PROMPTBOOK_ENGINE_VERSION = '0.88.0-1';
35
35
  /**
36
36
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
37
37
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -3972,7 +3972,7 @@ function valueToString(value) {
3972
3972
  * @param script from which to extract the variables
3973
3973
  * @returns the list of variable names
3974
3974
  * @throws {ParseError} if the script is invalid
3975
- * @public exported from `@promptbook/execute-javascript`
3975
+ * @public exported from `@promptbook/javascript`
3976
3976
  */
3977
3977
  function extractVariablesFromJavascript(script) {
3978
3978
  const variables = new Set();
@@ -5946,6 +5946,623 @@ async function $provideScrapersForNode(tools, options) {
5946
5946
  * Note: [🟢] Code in this file should never be never released in packages that could be imported into browser environment
5947
5947
  */
5948
5948
 
5949
+ /**
5950
+ * @@@
5951
+ *
5952
+ * @param text @@@
5953
+ * @param _isFirstLetterCapital @@@
5954
+ * @returns @@@
5955
+ * @example 'helloWorld'
5956
+ * @example 'iLovePromptbook'
5957
+ * @public exported from `@promptbook/utils`
5958
+ */
5959
+ function normalizeTo_camelCase(text, _isFirstLetterCapital = false) {
5960
+ let charType;
5961
+ let lastCharType = null;
5962
+ let normalizedName = '';
5963
+ for (const char of text) {
5964
+ let normalizedChar;
5965
+ if (/^[a-z]$/.test(char)) {
5966
+ charType = 'LOWERCASE';
5967
+ normalizedChar = char;
5968
+ }
5969
+ else if (/^[A-Z]$/.test(char)) {
5970
+ charType = 'UPPERCASE';
5971
+ normalizedChar = char.toLowerCase();
5972
+ }
5973
+ else if (/^[0-9]$/.test(char)) {
5974
+ charType = 'NUMBER';
5975
+ normalizedChar = char;
5976
+ }
5977
+ else {
5978
+ charType = 'OTHER';
5979
+ normalizedChar = '';
5980
+ }
5981
+ if (!lastCharType) {
5982
+ if (_isFirstLetterCapital) {
5983
+ normalizedChar = normalizedChar.toUpperCase(); //TODO: DRY
5984
+ }
5985
+ }
5986
+ else if (charType !== lastCharType &&
5987
+ !(charType === 'LOWERCASE' && lastCharType === 'UPPERCASE') &&
5988
+ !(lastCharType === 'NUMBER') &&
5989
+ !(charType === 'NUMBER')) {
5990
+ normalizedChar = normalizedChar.toUpperCase(); //TODO: [🌺] DRY
5991
+ }
5992
+ normalizedName += normalizedChar;
5993
+ lastCharType = charType;
5994
+ }
5995
+ return normalizedName;
5996
+ }
5997
+ /**
5998
+ * TODO: [🌺] Use some intermediate util splitWords
5999
+ */
6000
+
6001
+ /**
6002
+ * Detects if the code is running in a browser environment in main thread (Not in a web worker)
6003
+ *
6004
+ * Note: `$` is used to indicate that this function is not a pure function - it looks at the global object to determine the environment
6005
+ *
6006
+ * @public exported from `@promptbook/utils`
6007
+ */
6008
+ new Function(`
6009
+ try {
6010
+ return this === window;
6011
+ } catch (e) {
6012
+ return false;
6013
+ }
6014
+ `);
6015
+ /**
6016
+ * TODO: [🎺]
6017
+ */
6018
+
6019
+ /**
6020
+ * Detects if the code is running in jest environment
6021
+ *
6022
+ * Note: `$` is used to indicate that this function is not a pure function - it looks at the global object to determine the environment
6023
+ *
6024
+ * @public exported from `@promptbook/utils`
6025
+ */
6026
+ new Function(`
6027
+ try {
6028
+ return process.env.JEST_WORKER_ID !== undefined;
6029
+ } catch (e) {
6030
+ return false;
6031
+ }
6032
+ `);
6033
+ /**
6034
+ * TODO: [🎺]
6035
+ */
6036
+
6037
+ /**
6038
+ * Detects if the code is running in a web worker
6039
+ *
6040
+ * Note: `$` is used to indicate that this function is not a pure function - it looks at the global object to determine the environment
6041
+ *
6042
+ * @public exported from `@promptbook/utils`
6043
+ */
6044
+ new Function(`
6045
+ try {
6046
+ if (typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope) {
6047
+ return true;
6048
+ } else {
6049
+ return false;
6050
+ }
6051
+ } catch (e) {
6052
+ return false;
6053
+ }
6054
+ `);
6055
+ /**
6056
+ * TODO: [🎺]
6057
+ */
6058
+
6059
+ /**
6060
+ * Makes first letter of a string uppercase
6061
+ *
6062
+ * @public exported from `@promptbook/utils`
6063
+ */
6064
+ function decapitalize(word) {
6065
+ return word.substring(0, 1).toLowerCase() + word.substring(1);
6066
+ }
6067
+
6068
+ /**
6069
+ * Parses keywords from a string
6070
+ *
6071
+ * @param {string} input
6072
+ * @returns {Set} of keywords without diacritics in lowercase
6073
+ * @public exported from `@promptbook/utils`
6074
+ */
6075
+ function parseKeywordsFromString(input) {
6076
+ const keywords = normalizeTo_SCREAMING_CASE(removeDiacritics(input))
6077
+ .toLowerCase()
6078
+ .split(/[^a-z0-9]+/gs)
6079
+ .filter((value) => value);
6080
+ return new Set(keywords);
6081
+ }
6082
+
6083
+ /**
6084
+ * @@@
6085
+ *
6086
+ * @param name @@@
6087
+ * @returns @@@
6088
+ * @example @@@
6089
+ * @public exported from `@promptbook/utils`
6090
+ */
6091
+ function nameToUriPart(name) {
6092
+ let uriPart = name;
6093
+ uriPart = uriPart.toLowerCase();
6094
+ uriPart = removeDiacritics(uriPart);
6095
+ uriPart = uriPart.replace(/[^a-zA-Z0-9]+/g, '-');
6096
+ uriPart = uriPart.replace(/^-+/, '');
6097
+ uriPart = uriPart.replace(/-+$/, '');
6098
+ return uriPart;
6099
+ }
6100
+
6101
+ /**
6102
+ * @@@
6103
+ *
6104
+ * @param name @@@
6105
+ * @returns @@@
6106
+ * @example @@@
6107
+ * @public exported from `@promptbook/utils`
6108
+ */
6109
+ function nameToUriParts(name) {
6110
+ return nameToUriPart(name)
6111
+ .split('-')
6112
+ .filter((value) => value !== '');
6113
+ }
6114
+
6115
+ /**
6116
+ *
6117
+ * @param text @public exported from `@promptbook/utils`
6118
+ * @returns
6119
+ * @example 'HelloWorld'
6120
+ * @example 'ILovePromptbook'
6121
+ * @public exported from `@promptbook/utils`
6122
+ */
6123
+ function normalizeTo_PascalCase(text) {
6124
+ return normalizeTo_camelCase(text, true);
6125
+ }
6126
+
6127
+ /**
6128
+ * Take every whitespace (space, new line, tab) and replace it with a single space
6129
+ *
6130
+ * @public exported from `@promptbook/utils`
6131
+ */
6132
+ function normalizeWhitespaces(sentence) {
6133
+ return sentence.replace(/\s+/gs, ' ').trim();
6134
+ }
6135
+
6136
+ /**
6137
+ * Removes quotes from a string
6138
+ *
6139
+ * Tip: This is very usefull for post-processing of the result of the LLM model
6140
+ * Note: This function removes only the same quotes from the beginning and the end of the string
6141
+ * Note: There are two simmilar functions:
6142
+ * - `removeQuotes` which removes only bounding quotes
6143
+ * - `unwrapResult` which removes whole introduce sentence
6144
+ *
6145
+ * @param text optionally quoted text
6146
+ * @returns text without quotes
6147
+ * @public exported from `@promptbook/utils`
6148
+ */
6149
+ function removeQuotes(text) {
6150
+ if (text.startsWith('"') && text.endsWith('"')) {
6151
+ return text.slice(1, -1);
6152
+ }
6153
+ if (text.startsWith('\'') && text.endsWith('\'')) {
6154
+ return text.slice(1, -1);
6155
+ }
6156
+ return text;
6157
+ }
6158
+
6159
+ /**
6160
+ * Function trimCodeBlock will trim starting and ending code block from the string if it is present.
6161
+ *
6162
+ * Note: This is usefull for post-processing of the result of the chat LLM model
6163
+ * when the model wraps the result in the (markdown) code block.
6164
+ *
6165
+ * @public exported from `@promptbook/utils`
6166
+ */
6167
+ function trimCodeBlock(value) {
6168
+ value = spaceTrim(value);
6169
+ if (!/^```[a-z]*(.*)```$/is.test(value)) {
6170
+ return value;
6171
+ }
6172
+ value = value.replace(/^```[a-z]*/i, '');
6173
+ value = value.replace(/```$/i, '');
6174
+ value = spaceTrim(value);
6175
+ return value;
6176
+ }
6177
+
6178
+ /**
6179
+ * Function trimEndOfCodeBlock will remove ending code block from the string if it is present.
6180
+ *
6181
+ * Note: This is usefull for post-processing of the result of the completion LLM model
6182
+ * if you want to start code block in the prompt but you don't want to end it in the result.
6183
+ *
6184
+ * @public exported from `@promptbook/utils`
6185
+ */
6186
+ function trimEndOfCodeBlock(value) {
6187
+ value = spaceTrim(value);
6188
+ value = value.replace(/```$/g, '');
6189
+ value = spaceTrim(value);
6190
+ return value;
6191
+ }
6192
+
6193
+ /**
6194
+ * Removes quotes and optional introduce text from a string
6195
+ *
6196
+ * Tip: This is very usefull for post-processing of the result of the LLM model
6197
+ * Note: This function trims the text and removes whole introduce sentence if it is present
6198
+ * Note: There are two simmilar functions:
6199
+ * - `removeQuotes` which removes only bounding quotes
6200
+ * - `unwrapResult` which removes whole introduce sentence
6201
+ *
6202
+ * @param text optionally quoted text
6203
+ * @returns text without quotes
6204
+ * @public exported from `@promptbook/utils`
6205
+ */
6206
+ function unwrapResult(text, options) {
6207
+ const { isTrimmed = true, isIntroduceSentenceRemoved = true } = options || {};
6208
+ let trimmedText = text;
6209
+ // Remove leading and trailing spaces and newlines
6210
+ if (isTrimmed) {
6211
+ trimmedText = spaceTrim(trimmedText);
6212
+ }
6213
+ let processedText = trimmedText;
6214
+ if (isIntroduceSentenceRemoved) {
6215
+ const introduceSentenceRegex = /^[a-zěščřžýáíéúů:\s]*:\s*/i;
6216
+ if (introduceSentenceRegex.test(text)) {
6217
+ // Remove the introduce sentence and quotes by replacing it with an empty string
6218
+ processedText = processedText.replace(introduceSentenceRegex, '');
6219
+ }
6220
+ processedText = spaceTrim(processedText);
6221
+ }
6222
+ if (processedText.length < 3) {
6223
+ return trimmedText;
6224
+ }
6225
+ if (processedText.includes('\n')) {
6226
+ return trimmedText;
6227
+ }
6228
+ // Remove the quotes by extracting the substring without the first and last characters
6229
+ const unquotedText = processedText.slice(1, -1);
6230
+ // Check if the text starts and ends with quotes
6231
+ if ([
6232
+ ['"', '"'],
6233
+ ["'", "'"],
6234
+ ['`', '`'],
6235
+ ['*', '*'],
6236
+ ['_', '_'],
6237
+ ['„', '“'],
6238
+ ['«', '»'] /* <- QUOTES to config */,
6239
+ ].some(([startQuote, endQuote]) => {
6240
+ if (!processedText.startsWith(startQuote)) {
6241
+ return false;
6242
+ }
6243
+ if (!processedText.endsWith(endQuote)) {
6244
+ return false;
6245
+ }
6246
+ if (unquotedText.includes(startQuote) && !unquotedText.includes(endQuote)) {
6247
+ return false;
6248
+ }
6249
+ if (!unquotedText.includes(startQuote) && unquotedText.includes(endQuote)) {
6250
+ return false;
6251
+ }
6252
+ return true;
6253
+ })) {
6254
+ return unwrapResult(unquotedText, { isTrimmed: false, isIntroduceSentenceRemoved: false });
6255
+ }
6256
+ else {
6257
+ return processedText;
6258
+ }
6259
+ }
6260
+ /**
6261
+ * TODO: [🧠] Should this also unwrap the (parenthesis)
6262
+ */
6263
+
6264
+ /**
6265
+ * Extracts exactly ONE code block from markdown.
6266
+ *
6267
+ * - When there are multiple or no code blocks the function throws a `ParseError`
6268
+ *
6269
+ * Note: There are multiple simmilar function:
6270
+ * - `extractBlock` just extracts the content of the code block which is also used as build-in function for postprocessing
6271
+ * - `extractJsonBlock` extracts exactly one valid JSON code block
6272
+ * - `extractOneBlockFromMarkdown` extracts exactly one code block with language of the code block
6273
+ * - `extractAllBlocksFromMarkdown` extracts all code blocks with language of the code block
6274
+ *
6275
+ * @param markdown any valid markdown
6276
+ * @returns code block with language and content
6277
+ * @public exported from `@promptbook/markdown-utils`
6278
+ * @throws {ParseError} if there is not exactly one code block in the markdown
6279
+ */
6280
+ function extractOneBlockFromMarkdown(markdown) {
6281
+ const codeBlocks = extractAllBlocksFromMarkdown(markdown);
6282
+ if (codeBlocks.length !== 1) {
6283
+ throw new ParseError(spaceTrim$1((block) => `
6284
+ There should be exactly 1 code block in task section, found ${codeBlocks.length} code blocks
6285
+
6286
+ ${block(codeBlocks.map((block, i) => `Block ${i + 1}:\n${block.content}`).join('\n\n\n'))}
6287
+ `));
6288
+ }
6289
+ return codeBlocks[0];
6290
+ }
6291
+ /***
6292
+ * TODO: [🍓][🌻] Decide of this is internal utility, external util OR validator/postprocessor
6293
+ */
6294
+
6295
+ /**
6296
+ * Extracts code block from markdown.
6297
+ *
6298
+ * - When there are multiple or no code blocks the function throws a `ParseError`
6299
+ *
6300
+ * Note: There are multiple simmilar function:
6301
+ * - `extractBlock` just extracts the content of the code block which is also used as build-in function for postprocessing
6302
+ * - `extractJsonBlock` extracts exactly one valid JSON code block
6303
+ * - `extractOneBlockFromMarkdown` extracts exactly one code block with language of the code block
6304
+ * - `extractAllBlocksFromMarkdown` extracts all code blocks with language of the code block
6305
+ *
6306
+ * @public exported from `@promptbook/markdown-utils`
6307
+ * @throws {ParseError} if there is not exactly one code block in the markdown
6308
+ */
6309
+ function extractBlock(markdown) {
6310
+ const { content } = extractOneBlockFromMarkdown(markdown);
6311
+ return content;
6312
+ }
6313
+
6314
+ /**
6315
+ * Does nothing, but preserves the function in the bundle
6316
+ * Compiler is tricked into thinking the function is used
6317
+ *
6318
+ * @param value any function to preserve
6319
+ * @returns nothing
6320
+ * @private internal function of `JavascriptExecutionTools` and `JavascriptEvalExecutionTools`
6321
+ */
6322
+ function preserve(func) {
6323
+ // Note: NOT calling the function
6324
+ (async () => {
6325
+ // TODO: [💩] Change to `await forEver` or something better
6326
+ await forTime(100000000);
6327
+ // [1]
6328
+ try {
6329
+ await func();
6330
+ }
6331
+ finally {
6332
+ // do nothing
6333
+ }
6334
+ })();
6335
+ }
6336
+ /**
6337
+ * TODO: Probbably remove in favour of `keepImported`
6338
+ * TODO: [1] This maybe does memory leak
6339
+ */
6340
+
6341
+ // Note: [💎]
6342
+ /**
6343
+ * ScriptExecutionTools for JavaScript implemented via eval
6344
+ *
6345
+ * Warning: It is used for testing and mocking
6346
+ * **NOT intended to use in the production** due to its unsafe nature, use `JavascriptExecutionTools` instead.
6347
+ *
6348
+ * @public exported from `@promptbook/javascript`
6349
+ */
6350
+ class JavascriptEvalExecutionTools {
6351
+ constructor(options) {
6352
+ this.options = options || {};
6353
+ }
6354
+ /**
6355
+ * Executes a JavaScript
6356
+ */
6357
+ async execute(options) {
6358
+ const { scriptLanguage, parameters } = options;
6359
+ let { script } = options;
6360
+ if (scriptLanguage !== 'javascript') {
6361
+ throw new PipelineExecutionError(`Script language ${scriptLanguage} not supported to be executed by JavascriptEvalExecutionTools`);
6362
+ }
6363
+ // Note: [💎]
6364
+ // Note: Using direct eval, following variables are in same scope as eval call so they are accessible from inside the evaluated script:
6365
+ const spaceTrim = (_) => spaceTrim$1(_);
6366
+ preserve(spaceTrim);
6367
+ const removeQuotes$1 = removeQuotes;
6368
+ preserve(removeQuotes$1);
6369
+ const unwrapResult$1 = unwrapResult;
6370
+ preserve(unwrapResult$1);
6371
+ const trimEndOfCodeBlock$1 = trimEndOfCodeBlock;
6372
+ preserve(trimEndOfCodeBlock$1);
6373
+ const trimCodeBlock$1 = trimCodeBlock;
6374
+ preserve(trimCodeBlock$1);
6375
+ // TODO: DRY [🍯]
6376
+ const trim = (str) => str.trim();
6377
+ preserve(trim);
6378
+ // TODO: DRY [🍯]
6379
+ const reverse = (str) => str.split('').reverse().join('');
6380
+ preserve(reverse);
6381
+ const removeEmojis$1 = removeEmojis;
6382
+ preserve(removeEmojis$1);
6383
+ const prettifyMarkdown$1 = prettifyMarkdown;
6384
+ preserve(prettifyMarkdown$1);
6385
+ //-------[n12:]---
6386
+ const capitalize$1 = capitalize;
6387
+ const decapitalize$1 = decapitalize;
6388
+ const nameToUriPart$1 = nameToUriPart;
6389
+ const nameToUriParts$1 = nameToUriParts;
6390
+ const removeDiacritics$1 = removeDiacritics;
6391
+ const normalizeWhitespaces$1 = normalizeWhitespaces;
6392
+ const normalizeToKebabCase$1 = normalizeToKebabCase;
6393
+ const normalizeTo_camelCase$1 = normalizeTo_camelCase;
6394
+ const normalizeTo_snake_case$1 = normalizeTo_snake_case;
6395
+ const normalizeTo_PascalCase$1 = normalizeTo_PascalCase;
6396
+ const parseKeywords = (input) =>
6397
+ // TODO: DRY [🍯]
6398
+ Array.from(parseKeywordsFromString(input)).join(', '); /* <- TODO: [🧠] What is the best format comma list, bullet list,...? */
6399
+ const normalizeTo_SCREAMING_CASE$1 = normalizeTo_SCREAMING_CASE;
6400
+ preserve(capitalize$1);
6401
+ preserve(decapitalize$1);
6402
+ preserve(nameToUriPart$1);
6403
+ preserve(nameToUriParts$1);
6404
+ preserve(removeDiacritics$1);
6405
+ preserve(normalizeWhitespaces$1);
6406
+ preserve(normalizeToKebabCase$1);
6407
+ preserve(normalizeTo_camelCase$1);
6408
+ preserve(normalizeTo_snake_case$1);
6409
+ preserve(normalizeTo_PascalCase$1);
6410
+ preserve(parseKeywords);
6411
+ preserve(normalizeTo_SCREAMING_CASE$1);
6412
+ //-------[/n12]---
6413
+ if (!script.includes('return')) {
6414
+ script = `return ${script}`;
6415
+ }
6416
+ // TODO: DRY [🍯]
6417
+ const buildinFunctions = {
6418
+ // TODO: [🍯] DRY all these functions across the file
6419
+ spaceTrim,
6420
+ removeQuotes: removeQuotes$1,
6421
+ unwrapResult: unwrapResult$1,
6422
+ trimEndOfCodeBlock: trimEndOfCodeBlock$1,
6423
+ trimCodeBlock: trimCodeBlock$1,
6424
+ trim,
6425
+ reverse,
6426
+ removeEmojis: removeEmojis$1,
6427
+ prettifyMarkdown: prettifyMarkdown$1,
6428
+ capitalize: capitalize$1,
6429
+ decapitalize: decapitalize$1,
6430
+ nameToUriPart: nameToUriPart$1,
6431
+ nameToUriParts: nameToUriParts$1,
6432
+ removeDiacritics: removeDiacritics$1,
6433
+ normalizeWhitespaces: normalizeWhitespaces$1,
6434
+ normalizeToKebabCase: normalizeToKebabCase$1,
6435
+ normalizeTo_camelCase: normalizeTo_camelCase$1,
6436
+ normalizeTo_snake_case: normalizeTo_snake_case$1,
6437
+ normalizeTo_PascalCase: normalizeTo_PascalCase$1,
6438
+ parseKeywords,
6439
+ normalizeTo_SCREAMING_CASE: normalizeTo_SCREAMING_CASE$1,
6440
+ extractBlock, // <- [🍓] Remove balast in all other functions, use this one as example
6441
+ };
6442
+ const buildinFunctionsStatement = Object.keys(buildinFunctions)
6443
+ .map((functionName) =>
6444
+ // Note: Custom functions are exposed to the current scope as variables
6445
+ `const ${functionName} = buildinFunctions.${functionName};`)
6446
+ .join('\n');
6447
+ // TODO: DRY [🍯]
6448
+ const customFunctions = this.options.functions || {};
6449
+ const customFunctionsStatement = Object.keys(customFunctions)
6450
+ .map((functionName) =>
6451
+ // Note: Custom functions are exposed to the current scope as variables
6452
+ `const ${functionName} = customFunctions.${functionName};`)
6453
+ .join('\n');
6454
+ // script = templateParameters(script, parameters);
6455
+ // <- TODO: [🧠][🥳] Should be this is one of two variants how to use parameters in script
6456
+ const statementToEvaluate = spaceTrim$1((block) => `
6457
+
6458
+ // Build-in functions:
6459
+ ${block(buildinFunctionsStatement)}
6460
+
6461
+ // Custom functions:
6462
+ ${block(customFunctionsStatement || '// -- No custom functions --')}
6463
+
6464
+ // The script:
6465
+ ${block(Object.entries(parameters)
6466
+ .map(([key, value]) => `const ${key} = ${JSON.stringify(value)};`)
6467
+ .join('\n'))}
6468
+ (()=>{ ${script} })()
6469
+ `);
6470
+ if (this.options.isVerbose) {
6471
+ console.info(spaceTrim$1((block) => `
6472
+ 🚀 Evaluating ${scriptLanguage} script:
6473
+
6474
+ ${block(statementToEvaluate)}`));
6475
+ }
6476
+ let result;
6477
+ try {
6478
+ result = await eval(statementToEvaluate);
6479
+ if (typeof result !== 'string') {
6480
+ throw new PipelineExecutionError(`Script must return a string, but returned ${valueToString(result)}`);
6481
+ }
6482
+ }
6483
+ catch (error) {
6484
+ if (!(error instanceof Error)) {
6485
+ throw error;
6486
+ }
6487
+ if (error instanceof ReferenceError) {
6488
+ const undefinedName = error.message.split(' ')[0];
6489
+ /*
6490
+ Note: Remapping error
6491
+ From: [PipelineUrlError: thing is not defined],
6492
+ To: [PipelineExecutionError: Parameter `{thing}` is not defined],
6493
+ */
6494
+ if (!statementToEvaluate.includes(undefinedName + '(')) {
6495
+ throw new PipelineExecutionError(spaceTrim$1((block) => `
6496
+
6497
+ Parameter \`{${undefinedName}}\` is not defined
6498
+
6499
+ This happen during evaluation of the javascript, which has access to the following parameters as javascript variables:
6500
+
6501
+ ${block(Object.keys(parameters)
6502
+ .map((key) => ` - ${key}\n`)
6503
+ .join(''))}
6504
+
6505
+ The script is:
6506
+ \`\`\`javascript
6507
+ ${block(script)}
6508
+ \`\`\`
6509
+
6510
+ Original error message:
6511
+ ${block(error.message)}
6512
+
6513
+
6514
+ `));
6515
+ }
6516
+ else {
6517
+ throw new PipelineExecutionError(spaceTrim$1((block) => `
6518
+ Function ${undefinedName}() is not defined
6519
+
6520
+ - Make sure that the function is one of built-in functions
6521
+ - Or you have to defined the function during construction of JavascriptEvalExecutionTools
6522
+
6523
+ Original error message:
6524
+ ${block(error.message)}
6525
+
6526
+ `));
6527
+ }
6528
+ }
6529
+ throw error;
6530
+ }
6531
+ if (typeof result !== 'string') {
6532
+ throw new PipelineExecutionError(`Script must return a string, but ${valueToString(result)}`);
6533
+ }
6534
+ return result;
6535
+ }
6536
+ }
6537
+ /**
6538
+ * TODO: Put predefined functions (like removeQuotes, spaceTrim, etc.) into annotation OR pass into constructor
6539
+ * TODO: [🧠][💙] Distinct between options passed into ExecutionTools and to ExecutionTools.execute
6540
+ */
6541
+
6542
+ /**
6543
+ * Placeholder for better implementation of JavascriptExecutionTools - some propper sandboxing
6544
+ *
6545
+ * @alias JavascriptExecutionTools
6546
+ * @public exported from `@promptbook/javascript`
6547
+ */
6548
+ const JavascriptExecutionTools = JavascriptEvalExecutionTools;
6549
+
6550
+ /**
6551
+ * Provides script execution tools
6552
+ *
6553
+ * @public exported from `@promptbook/node`
6554
+ */
6555
+ async function $provideScriptingForNode(options) {
6556
+ if (!$isRunningInNode()) {
6557
+ throw new EnvironmentMismatchError('Function `$provideScriptingForNode` works only in Node.js environment');
6558
+ }
6559
+ // TODO: [🔱] Do here auto-installation
6560
+ return [new JavascriptExecutionTools(options)];
6561
+ }
6562
+ /**
6563
+ * Note: [🟢] Code in this file should never be never released in packages that could be imported into browser environment
6564
+ */
6565
+
5949
6566
  /**
5950
6567
  * Remote server is a proxy server that uses its execution tools internally and exposes the executor interface externally.
5951
6568
  *
@@ -6017,7 +6634,7 @@ function startRemoteServer(options) {
6017
6634
  llm,
6018
6635
  fs,
6019
6636
  scrapers: await $provideScrapersForNode({ fs, llm, executables }),
6020
- // TODO: Allow when `JavascriptExecutionTools` more secure *(without eval)*> script: [new JavascriptExecutionTools()],
6637
+ script: await $provideScriptingForNode({}),
6021
6638
  };
6022
6639
  return tools;
6023
6640
  }
@@ -6028,6 +6645,7 @@ function startRemoteServer(options) {
6028
6645
  next();
6029
6646
  });
6030
6647
  const runningExecutionTasks = [];
6648
+ // <- TODO: [🤬] Identify the users
6031
6649
  // TODO: [🧠] Do here some garbage collection of finished tasks
6032
6650
  app.get(['/', rootPath], async (request, response) => {
6033
6651
  var _a;
@@ -6125,8 +6743,18 @@ function startRemoteServer(options) {
6125
6743
  app.get(`${rootPath}/executions`, async (request, response) => {
6126
6744
  response.send(runningExecutionTasks);
6127
6745
  });
6746
+ app.get(`${rootPath}/executions/last`, async (request, response) => {
6747
+ // TODO: [🤬] Filter only for user
6748
+ if (runningExecutionTasks.length === 0) {
6749
+ response.status(404).send('No execution tasks found');
6750
+ return;
6751
+ }
6752
+ const lastExecution = runningExecutionTasks[runningExecutionTasks.length - 1];
6753
+ response.send(lastExecution);
6754
+ });
6128
6755
  app.get(`${rootPath}/executions/:taskId`, async (request, response) => {
6129
6756
  const { taskId } = request.params;
6757
+ // TODO: [🤬] Filter only for user
6130
6758
  const execution = runningExecutionTasks.find((executionTask) => executionTask.taskId === taskId);
6131
6759
  if (execution === undefined) {
6132
6760
  response
@@ -6138,7 +6766,7 @@ function startRemoteServer(options) {
6138
6766
  });
6139
6767
  app.post(`${rootPath}/executions/new`, async (request, response) => {
6140
6768
  try {
6141
- const { inputParameters, identification } = request.body;
6769
+ const { inputParameters, identification /* <- [🤬] */ } = request.body;
6142
6770
  const pipelineUrl = request.body.pipelineUrl || request.body.book;
6143
6771
  // TODO: [🧠] Check `pipelineUrl` and `inputParameters` here or it should be responsibility of `collection.getPipelineByUrl` and `pipelineExecutor`
6144
6772
  const pipeline = await (collection === null || collection === void 0 ? void 0 : collection.getPipelineByUrl(pipelineUrl));