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