@promptbook/utils 0.52.0-3 → 0.52.0-30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/README.md +1 -3
  2. package/esm/index.es.js +559 -1597
  3. package/esm/index.es.js.map +1 -1
  4. package/esm/typings/_packages/core.index.d.ts +15 -6
  5. package/esm/typings/_packages/utils.index.d.ts +5 -8
  6. package/esm/typings/execution/ExecutionTools.d.ts +5 -3
  7. package/esm/typings/execution/plugins/llm-execution-tools/anthropic-claude/AnthropicClaudeExecutionTools.d.ts +0 -1
  8. package/esm/typings/execution/plugins/llm-execution-tools/azure-openai/AzureOpenAiExecutionTools.d.ts +0 -1
  9. package/esm/typings/execution/plugins/llm-execution-tools/langtail/LangtailExecutionTools.d.ts +0 -3
  10. package/esm/typings/execution/plugins/llm-execution-tools/openai/OpenAiExecutionTools.d.ts +1 -1
  11. package/esm/typings/execution/plugins/llm-execution-tools/remote/RemoteLlmExecutionTools.d.ts +1 -1
  12. package/esm/typings/execution/plugins/script-execution-tools/javascript/JavascriptEvalExecutionTools.d.ts +1 -1
  13. package/esm/typings/execution/plugins/script-execution-tools/javascript/JavascriptExecutionTools.d.ts +4 -17
  14. package/esm/typings/execution/utils/forEachAsync.d.ts +18 -0
  15. package/esm/typings/library/constructors/createPromptbookLibraryFromDirectory.d.ts +36 -4
  16. package/esm/typings/library/constructors/createPromptbookLibraryFromDirectory.test.d.ts +1 -0
  17. package/esm/typings/library/constructors/createPromptbookLibraryFromPromise.d.ts +2 -2
  18. package/esm/typings/library/constructors/createPromptbookLibraryFromPromise.test.d.ts +1 -0
  19. package/esm/typings/library/constructors/createPromptbookLibraryFromSources.test.d.ts +1 -0
  20. package/esm/typings/library/constructors/createPromptbookLibraryFromUrl.d.ts +21 -5
  21. package/esm/typings/library/constructors/justTestFsImport.d.ts +7 -0
  22. package/esm/typings/types/Prompt.d.ts +1 -1
  23. package/esm/typings/types/typeAliases.d.ts +2 -2
  24. package/package.json +2 -4
  25. package/umd/index.umd.js +563 -1608
  26. package/umd/index.umd.js.map +1 -1
  27. package/umd/typings/_packages/core.index.d.ts +15 -6
  28. package/umd/typings/_packages/utils.index.d.ts +5 -8
  29. package/umd/typings/execution/ExecutionTools.d.ts +5 -3
  30. package/umd/typings/execution/plugins/llm-execution-tools/anthropic-claude/AnthropicClaudeExecutionTools.d.ts +0 -1
  31. package/umd/typings/execution/plugins/llm-execution-tools/azure-openai/AzureOpenAiExecutionTools.d.ts +0 -1
  32. package/umd/typings/execution/plugins/llm-execution-tools/langtail/LangtailExecutionTools.d.ts +0 -3
  33. package/umd/typings/execution/plugins/llm-execution-tools/openai/OpenAiExecutionTools.d.ts +1 -1
  34. package/umd/typings/execution/plugins/llm-execution-tools/remote/RemoteLlmExecutionTools.d.ts +1 -1
  35. package/umd/typings/execution/plugins/script-execution-tools/javascript/JavascriptEvalExecutionTools.d.ts +1 -1
  36. package/umd/typings/execution/plugins/script-execution-tools/javascript/JavascriptExecutionTools.d.ts +4 -17
  37. package/umd/typings/execution/utils/forEachAsync.d.ts +18 -0
  38. package/umd/typings/library/constructors/createPromptbookLibraryFromDirectory.d.ts +36 -4
  39. package/umd/typings/library/constructors/createPromptbookLibraryFromDirectory.test.d.ts +1 -0
  40. package/umd/typings/library/constructors/createPromptbookLibraryFromPromise.d.ts +2 -2
  41. package/umd/typings/library/constructors/createPromptbookLibraryFromPromise.test.d.ts +1 -0
  42. package/umd/typings/library/constructors/createPromptbookLibraryFromSources.test.d.ts +1 -0
  43. package/umd/typings/library/constructors/createPromptbookLibraryFromUrl.d.ts +21 -5
  44. package/umd/typings/library/constructors/justTestFsImport.d.ts +7 -0
  45. package/umd/typings/types/Prompt.d.ts +1 -1
  46. package/umd/typings/types/typeAliases.d.ts +2 -2
  47. package/esm/typings/_packages/wizzard.index.d.ts +0 -5
  48. package/esm/typings/wizzard/Wizzard.d.ts +0 -4
  49. package/esm/typings/wizzard/sample.d.ts +0 -6
  50. package/umd/typings/_packages/wizzard.index.d.ts +0 -5
  51. package/umd/typings/wizzard/Wizzard.d.ts +0 -4
  52. package/umd/typings/wizzard/sample.d.ts +0 -6
package/esm/index.es.js CHANGED
@@ -1,8 +1,5 @@
1
1
  import { spaceTrim } from 'spacetrim';
2
2
  export { spaceTrim } from 'spacetrim';
3
- import { format } from 'prettier';
4
- import parserHtml from 'prettier/parser-html';
5
- import moment from 'moment';
6
3
 
7
4
  /*! *****************************************************************************
8
5
  Copyright (c) Microsoft Corporation.
@@ -46,6 +43,44 @@ var __assign = function() {
46
43
  return __assign.apply(this, arguments);
47
44
  };
48
45
 
46
+ function __awaiter(thisArg, _arguments, P, generator) {
47
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
48
+ return new (P || (P = Promise))(function (resolve, reject) {
49
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
50
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
51
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
52
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
53
+ });
54
+ }
55
+
56
+ function __generator(thisArg, body) {
57
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
58
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
59
+ function verb(n) { return function (v) { return step([n, v]); }; }
60
+ function step(op) {
61
+ if (f) throw new TypeError("Generator is already executing.");
62
+ while (_) try {
63
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
64
+ if (y = 0, t) op = [op[0] & 2, t.value];
65
+ switch (op[0]) {
66
+ case 0: case 1: t = op; break;
67
+ case 4: _.label++; return { value: op[1], done: false };
68
+ case 5: _.label++; y = op[1]; op = [0]; continue;
69
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
70
+ default:
71
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
72
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
73
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
74
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
75
+ if (t[2]) _.ops.pop();
76
+ _.trys.pop(); continue;
77
+ }
78
+ op = body.call(thisArg, _);
79
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
80
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
81
+ }
82
+ }
83
+
49
84
  function __values(o) {
50
85
  var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
51
86
  if (m) return m.call(o);
@@ -86,496 +121,241 @@ function __spreadArray(to, from, pack) {
86
121
  }
87
122
 
88
123
  /**
89
- * This error indicates that the promptbook in a markdown format cannot be parsed into a valid promptbook object
124
+ * This error type indicates that the error should not happen and its last check before crashing with some other error
90
125
  */
91
- var PromptbookSyntaxError = /** @class */ (function (_super) {
92
- __extends(PromptbookSyntaxError, _super);
93
- function PromptbookSyntaxError(message) {
94
- var _this = _super.call(this, message) || this;
95
- _this.name = 'PromptbookSyntaxError';
96
- Object.setPrototypeOf(_this, PromptbookSyntaxError.prototype);
126
+ var UnexpectedError = /** @class */ (function (_super) {
127
+ __extends(UnexpectedError, _super);
128
+ function UnexpectedError(message) {
129
+ var _this = _super.call(this, spaceTrim(function (block) { return "\n ".concat(block(message), "\n\n Note: This error should not happen.\n It's probbably a bug in the promptbook library\n\n Please report issue:\n https://github.com/webgptorg/promptbook/issues\n\n Or contact us on me@pavolhejny.com\n\n "); })) || this;
130
+ _this.name = 'UnexpectedError';
131
+ Object.setPrototypeOf(_this, UnexpectedError.prototype);
97
132
  return _this;
98
133
  }
99
- return PromptbookSyntaxError;
134
+ return UnexpectedError;
100
135
  }(Error));
101
136
 
102
137
  /**
103
- * Supported script languages
138
+ * Removes emojis from a string and fix whitespaces
139
+ *
140
+ * @param text with emojis
141
+ * @returns text without emojis
142
+ */
143
+ function removeEmojis(text) {
144
+ // Replace emojis (and also ZWJ sequence) with hyphens
145
+ text = text.replace(/(\p{Extended_Pictographic})\p{Modifier_Symbol}/gu, '$1');
146
+ text = text.replace(/(\p{Extended_Pictographic})[\u{FE00}-\u{FE0F}]/gu, '$1');
147
+ text = text.replace(/(\p{Extended_Pictographic})(\u{200D}\p{Extended_Pictographic})*/gu, '$1');
148
+ text = text.replace(/\p{Extended_Pictographic}/gu, '');
149
+ return text;
150
+ }
151
+
152
+ /**
153
+ * Function normalizes title to name which can be used as identifier
154
+ */
155
+ function titleToName(value) {
156
+ value = removeEmojis(value);
157
+ value = normalizeToKebabCase(value);
158
+ // TODO: [🧠] Maybe warn or add some padding to short name which are not good identifiers
159
+ return value;
160
+ }
161
+
162
+ /**
163
+ * Creates a Mermaid graph based on the promptbook
164
+ *
165
+ * Note: The result is not wrapped in a Markdown code block
166
+ */
167
+ function renderPromptbookMermaid(promptbookJson, options) {
168
+ var _a = (options || {}).linkPromptTemplate, linkPromptTemplate = _a === void 0 ? function () { return null; } : _a;
169
+ var parameterNameToTemplateName = function (parameterName) {
170
+ var parameter = promptbookJson.parameters.find(function (parameter) { return parameter.name === parameterName; });
171
+ if (!parameter) {
172
+ throw new UnexpectedError("Could not find {".concat(parameterName, "}"));
173
+ }
174
+ if (parameter.isInput) {
175
+ return 'input';
176
+ }
177
+ var template = promptbookJson.promptTemplates.find(function (template) { return template.resultingParameterName === parameterName; });
178
+ if (!template) {
179
+ throw new Error("Could not find template for {".concat(parameterName, "}"));
180
+ }
181
+ return normalizeTo_camelCase('template-' + titleToName(template.title));
182
+ };
183
+ var promptbookMermaid = spaceTrim(function (block) { return "\n\n %% \uD83D\uDD2E Tip: Open this on GitHub or in the VSCode website to see the Mermaid graph visually\n\n flowchart LR\n subgraph \"".concat(promptbookJson.title, "\"\n\n direction TB\n\n input((Input)):::input\n ").concat(block(promptbookJson.promptTemplates
184
+ .flatMap(function (_a) {
185
+ var title = _a.title, dependentParameterNames = _a.dependentParameterNames, resultingParameterName = _a.resultingParameterName;
186
+ return __spreadArray([
187
+ "".concat(parameterNameToTemplateName(resultingParameterName), "(\"").concat(title, "\")")
188
+ ], __read(dependentParameterNames.map(function (dependentParameterName) {
189
+ return "".concat(parameterNameToTemplateName(dependentParameterName), "--\"{").concat(dependentParameterName, "}\"-->").concat(parameterNameToTemplateName(resultingParameterName));
190
+ })), false);
191
+ })
192
+ .join('\n')), "\n\n ").concat(block(promptbookJson.parameters
193
+ .filter(function (_a) {
194
+ var isOutput = _a.isOutput;
195
+ return isOutput;
196
+ })
197
+ .map(function (_a) {
198
+ var name = _a.name;
199
+ return "".concat(parameterNameToTemplateName(name), "--\"{").concat(name, "}\"-->output");
200
+ })
201
+ .join('\n')), "\n output((Output)):::output\n\n ").concat(block(promptbookJson.promptTemplates
202
+ .map(function (promptTemplate) {
203
+ var link = linkPromptTemplate(promptTemplate);
204
+ if (link === null) {
205
+ return '';
206
+ }
207
+ var href = link.href, title = link.title;
208
+ var templateName = parameterNameToTemplateName(promptTemplate.resultingParameterName);
209
+ return "click ".concat(templateName, " href \"").concat(href, "\" \"").concat(title, "\";");
210
+ })
211
+ .filter(function (line) { return line !== ''; })
212
+ .join('\n')), "\n\n classDef input color: grey;\n classDef output color: grey;\n\n end;\n\n "); });
213
+ return promptbookMermaid;
214
+ }
215
+ /**
216
+ * TODO: Maybe use some Mermaid library instead of string templating
217
+ * TODO: [🕌] When more than 2 functionalities, split into separate functions
104
218
  */
105
- var SUPPORTED_SCRIPT_LANGUAGES = ['javascript', 'typescript', 'python'];
106
219
 
107
220
  /**
108
- * Computes the deepness of the markdown structure.
221
+ * Parses the template and returns the list of all parameter names
109
222
  *
110
- * @private within the library
223
+ * @param template the template with parameters in {curly} braces
224
+ * @returns the list of parameter names
111
225
  */
112
- function countMarkdownStructureDeepness(markdownStructure) {
226
+ function extractParameters(template) {
113
227
  var e_1, _a;
114
- var maxDeepness = 0;
228
+ var matches = template.matchAll(/{\w+}/g);
229
+ var parameterNames = new Set();
115
230
  try {
116
- for (var _b = __values(markdownStructure.sections), _c = _b.next(); !_c.done; _c = _b.next()) {
117
- var section = _c.value;
118
- maxDeepness = Math.max(maxDeepness, countMarkdownStructureDeepness(section));
231
+ for (var matches_1 = __values(matches), matches_1_1 = matches_1.next(); !matches_1_1.done; matches_1_1 = matches_1.next()) {
232
+ var match = matches_1_1.value;
233
+ var parameterName = match[0].slice(1, -1);
234
+ parameterNames.add(parameterName);
119
235
  }
120
236
  }
121
237
  catch (e_1_1) { e_1 = { error: e_1_1 }; }
122
238
  finally {
123
239
  try {
124
- if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
240
+ if (matches_1_1 && !matches_1_1.done && (_a = matches_1.return)) _a.call(matches_1);
125
241
  }
126
242
  finally { if (e_1) throw e_1.error; }
127
243
  }
128
- return maxDeepness + 1;
244
+ return parameterNames;
129
245
  }
130
246
 
131
247
  /**
132
- * The maximum number of iterations for a loops
133
- */
134
- var LOOP_LIMIT = 1000;
135
-
136
- /**
137
- * This error type indicates that the error should not happen and its last check before crashing with some other error
248
+ * This error indicates that the promptbook in a markdown format cannot be parsed into a valid promptbook object
138
249
  */
139
- var UnexpectedError = /** @class */ (function (_super) {
140
- __extends(UnexpectedError, _super);
141
- function UnexpectedError(message) {
142
- var _this = _super.call(this, spaceTrim(function (block) { return "\n ".concat(block(message), "\n\n Note: This error should not happen.\n It's probbably a bug in the promptbook library\n\n Please report issue:\n https://github.com/webgptorg/promptbook/issues\n\n Or contact us on me@pavolhejny.com\n\n "); })) || this;
143
- _this.name = 'UnexpectedError';
144
- Object.setPrototypeOf(_this, UnexpectedError.prototype);
250
+ var PromptbookSyntaxError = /** @class */ (function (_super) {
251
+ __extends(PromptbookSyntaxError, _super);
252
+ function PromptbookSyntaxError(message) {
253
+ var _this = _super.call(this, message) || this;
254
+ _this.name = 'PromptbookSyntaxError';
255
+ Object.setPrototypeOf(_this, PromptbookSyntaxError.prototype);
145
256
  return _this;
146
257
  }
147
- return UnexpectedError;
258
+ return PromptbookSyntaxError;
148
259
  }(Error));
149
260
 
150
261
  /**
151
- * Parse a markdown string into a MarkdownStructure object.
152
- *
153
- * Note: This function does work with code blocks
154
- * Note: This function does not work with markdown comments
155
- *
156
- * @param markdown The markdown string to parse.
157
- * @returns The MarkdownStructure object.
262
+ * Parses the given script and returns the list of all used variables that are not defined in the script
158
263
  *
159
- * @private within the library
264
+ * @param script from which to extract the variables
265
+ * @returns the list of variable names
266
+ * @throws {PromptbookSyntaxError} if the script is invalid
160
267
  */
161
- function markdownToMarkdownStructure(markdown) {
162
- var e_1, _a;
163
- var lines = markdown.split('\n');
164
- var root = { level: 0, title: '', contentLines: [], sections: [], parent: null };
165
- var current = root;
166
- var isInsideCodeBlock = false;
268
+ function extractVariables(script) {
269
+ var variables = new Set();
270
+ script = "(()=>{".concat(script, "})()");
167
271
  try {
168
- for (var lines_1 = __values(lines), lines_1_1 = lines_1.next(); !lines_1_1.done; lines_1_1 = lines_1.next()) {
169
- var line = lines_1_1.value;
170
- var headingMatch = line.match(/^(?<mark>#{1,6})\s(?<title>.*)/);
171
- if (isInsideCodeBlock || !headingMatch) {
172
- if (line.startsWith('```')) {
173
- isInsideCodeBlock = !isInsideCodeBlock;
174
- }
175
- current.contentLines.push(line);
272
+ for (var i = 0; i < 100 /* <- TODO: This limit to configuration */; i++)
273
+ try {
274
+ eval(script);
176
275
  }
177
- else {
178
- var level = headingMatch.groups.mark.length;
179
- var title = headingMatch.groups.title.trim();
180
- var parent_1 = void 0;
181
- if (level > current.level) {
182
- // Note: Going deeper (next section is child of current)
183
- parent_1 = current;
276
+ catch (error) {
277
+ if (!(error instanceof ReferenceError)) {
278
+ throw error;
279
+ }
280
+ var undefinedName = error.message.split(' ')[0];
281
+ /*
282
+ Note: Remapping error
283
+ From: [ReferenceError: thing is not defined],
284
+ To: [Error: Parameter {thing} is not defined],
285
+ */
286
+ if (!undefinedName) {
287
+ throw error;
288
+ }
289
+ if (script.includes(undefinedName + '(')) {
290
+ script = "const ".concat(undefinedName, " = ()=>'';") + script;
184
291
  }
185
292
  else {
186
- // Note: Going up or staying at the same level (next section is sibling or parent or grandparent,... of current)
187
- parent_1 = current;
188
- var loopLimit = LOOP_LIMIT;
189
- while (parent_1.level !== level - 1) {
190
- if (loopLimit-- < 0) {
191
- throw new UnexpectedError('Loop limit reached during parsing of markdown structure in `markdownToMarkdownStructure`');
192
- }
193
- if (parent_1.parent === null /* <- Note: We are in root */) {
194
- // [🌻]
195
- throw new Error(spaceTrim("\n The file has an invalid structure.\n The markdown file must have exactly one top-level section.\n "));
196
- }
197
- parent_1 = parent_1.parent;
198
- }
293
+ variables.add(undefinedName);
294
+ script = "const ".concat(undefinedName, " = '';") + script;
199
295
  }
200
- var section = { level: level, title: title, contentLines: [], sections: [], parent: parent_1 };
201
- parent_1.sections.push(section);
202
- current = section;
203
296
  }
204
- }
205
297
  }
206
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
207
- finally {
208
- try {
209
- if (lines_1_1 && !lines_1_1.done && (_a = lines_1.return)) _a.call(lines_1);
298
+ catch (error) {
299
+ if (!(error instanceof Error)) {
300
+ throw error;
210
301
  }
211
- finally { if (e_1) throw e_1.error; }
212
- }
213
- if (root.sections.length === 1) {
214
- var markdownStructure = parsingMarkdownStructureToMarkdownStructure(root.sections[0]);
215
- return markdownStructure;
302
+ throw new PromptbookSyntaxError(spaceTrim(function (block) { return "\n Can not extract variables from the script\n\n ".concat(block(error.name), ": ").concat(block(error.message), "\n "); }));
216
303
  }
217
- // [🌻]
218
- throw new Error('The markdown file must have exactly one top-level section.');
219
- // return root;
304
+ return variables;
220
305
  }
221
306
  /**
222
- * @private
307
+ * TODO: [🔣] Support for multiple languages - python, java,...
223
308
  */
224
- function parsingMarkdownStructureToMarkdownStructure(parsingMarkdownStructure) {
225
- var level = parsingMarkdownStructure.level, title = parsingMarkdownStructure.title, contentLines = parsingMarkdownStructure.contentLines, sections = parsingMarkdownStructure.sections;
226
- return {
227
- level: level,
228
- title: title,
229
- content: spaceTrim(contentLines.join('\n')),
230
- sections: sections.map(parsingMarkdownStructureToMarkdownStructure),
231
- };
232
- }
233
309
 
234
310
  /**
235
- * Utility function to extract all list items from markdown
236
- *
237
- * Note: It works with both ul and ol
238
- * Note: It omits list items in code blocks
239
- * Note: It flattens nested lists
240
- * Note: It can not work with html syntax and comments
311
+ * Parses the prompt template and returns the set of all used parameters
241
312
  *
242
- * @param markdown any valid markdown
243
- * @returns
313
+ * @param promptTemplate the template with used parameters
314
+ * @returns the set of parameter names
315
+ * @throws {PromptbookSyntaxError} if the script is invalid
244
316
  */
245
- function extractAllListItemsFromMarkdown(markdown) {
246
- var e_1, _a;
247
- var lines = markdown.split('\n');
248
- var listItems = [];
249
- var isInCodeBlock = false;
317
+ function extractParametersFromPromptTemplate(promptTemplate) {
318
+ var e_1, _a, e_2, _b;
319
+ var parameterNames = new Set();
250
320
  try {
251
- for (var lines_1 = __values(lines), lines_1_1 = lines_1.next(); !lines_1_1.done; lines_1_1 = lines_1.next()) {
252
- var line = lines_1_1.value;
253
- var trimmedLine = line.trim();
254
- if (trimmedLine.startsWith('```')) {
255
- isInCodeBlock = !isInCodeBlock;
256
- }
257
- if (!isInCodeBlock && (trimmedLine.startsWith('-') || trimmedLine.match(/^\d+\./))) {
258
- var listItem = trimmedLine.replace(/^-|\d+\./, '').trim();
259
- listItems.push(listItem);
260
- }
321
+ for (var _c = __values(__spreadArray(__spreadArray(__spreadArray([], __read(extractParameters(promptTemplate.title)), false), __read(extractParameters(promptTemplate.description || '')), false), __read(extractParameters(promptTemplate.content)), false)), _d = _c.next(); !_d.done; _d = _c.next()) {
322
+ var parameterName = _d.value;
323
+ parameterNames.add(parameterName);
261
324
  }
262
325
  }
263
326
  catch (e_1_1) { e_1 = { error: e_1_1 }; }
264
327
  finally {
265
328
  try {
266
- if (lines_1_1 && !lines_1_1.done && (_a = lines_1.return)) _a.call(lines_1);
329
+ if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
267
330
  }
268
331
  finally { if (e_1) throw e_1.error; }
269
332
  }
270
- return listItems;
333
+ if (promptTemplate.executionType === 'SCRIPT') {
334
+ try {
335
+ for (var _e = __values(extractVariables(promptTemplate.content)), _f = _e.next(); !_f.done; _f = _e.next()) {
336
+ var parameterName = _f.value;
337
+ parameterNames.add(parameterName);
338
+ }
339
+ }
340
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
341
+ finally {
342
+ try {
343
+ if (_f && !_f.done && (_b = _e.return)) _b.call(_e);
344
+ }
345
+ finally { if (e_2) throw e_2.error; }
346
+ }
347
+ }
348
+ return parameterNames;
271
349
  }
272
-
273
350
  /**
274
- * Makes first letter of a string uppercase
275
- *
351
+ * TODO: [🔣] If script require contentLanguage
276
352
  */
277
- function capitalize(word) {
278
- return word.substring(0, 1).toUpperCase() + word.substring(1);
279
- }
280
353
 
281
354
  /**
282
- * Extracts all code blocks from markdown.
283
- *
284
- * Note: There are 3 simmilar function:
285
- * - `extractBlock` just extracts the content of the code block which is also used as build-in function for postprocessing
286
- * - `extractOneBlockFromMarkdown` extracts exactly one code block with language of the code block
287
- * - `extractAllBlocksFromMarkdown` extracts all code blocks with language of the code block
355
+ * Function parseNumber will parse number from string
288
356
  *
289
- * @param markdown any valid markdown
290
- * @returns code blocks with language and content
291
- *
292
- */
293
- function extractAllBlocksFromMarkdown(markdown) {
294
- var e_1, _a;
295
- var codeBlocks = [];
296
- var lines = markdown.split('\n');
297
- var currentCodeBlock = null;
298
- try {
299
- for (var lines_1 = __values(lines), lines_1_1 = lines_1.next(); !lines_1_1.done; lines_1_1 = lines_1.next()) {
300
- var line = lines_1_1.value;
301
- if (line.startsWith('```')) {
302
- var language = line.slice(3).trim() || null;
303
- if (currentCodeBlock === null) {
304
- currentCodeBlock = { language: language, content: '' };
305
- }
306
- else {
307
- if (language !== null) {
308
- // [🌻]
309
- throw new Error("".concat(capitalize(currentCodeBlock.language || 'the'), " code block was not closed and already opening new ").concat(language, " code block"));
310
- }
311
- codeBlocks.push(currentCodeBlock);
312
- currentCodeBlock = null;
313
- }
314
- }
315
- else if (currentCodeBlock !== null) {
316
- if (currentCodeBlock.content !== '') {
317
- currentCodeBlock.content += '\n';
318
- }
319
- currentCodeBlock.content += line.split('\\`\\`\\`').join('```') /* <- TODO: Maybe make propper unescape */;
320
- }
321
- }
322
- }
323
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
324
- finally {
325
- try {
326
- if (lines_1_1 && !lines_1_1.done && (_a = lines_1.return)) _a.call(lines_1);
327
- }
328
- finally { if (e_1) throw e_1.error; }
329
- }
330
- if (currentCodeBlock !== null) {
331
- // [🌻]
332
- throw new Error("".concat(capitalize(currentCodeBlock.language || 'the'), " code block was not closed at the end of the markdown"));
333
- }
334
- return codeBlocks;
335
- }
336
-
337
- /**
338
- * Extracts exactly ONE code block from markdown.
339
- *
340
- * Note: If there are multiple or no code blocks the function throws an error
341
- *
342
- * Note: There are 3 simmilar function:
343
- * - `extractBlock` just extracts the content of the code block which is also used as build-in function for postprocessing
344
- * - `extractOneBlockFromMarkdown` extracts exactly one code block with language of the code block
345
- * - `extractAllBlocksFromMarkdown` extracts all code blocks with language of the code block
346
- *
347
- * @param markdown any valid markdown
348
- * @returns code block with language and content
349
- */
350
- function extractOneBlockFromMarkdown(markdown) {
351
- var codeBlocks = extractAllBlocksFromMarkdown(markdown);
352
- if (codeBlocks.length !== 1) {
353
- // TODO: Report more specific place where the error happened
354
- throw new Error(/* <- [🌻] */ 'There should be exactly one code block in the markdown');
355
- }
356
- return codeBlocks[0];
357
- }
358
- /***
359
- * TODO: [🍓][🌻] !!! Decide of this is internal util, external util OR validator/postprocessor
360
- */
361
-
362
- /**
363
- * Removes HTML or Markdown comments from a string.
364
- *
365
- * @param {string} content - The string to remove comments from.
366
- * @returns {string} The input string with all comments removed.
367
- */
368
- function removeContentComments(content) {
369
- return spaceTrim(content.replace(/<!--(.*?)-->/gs, ''));
370
- }
371
-
372
- /**
373
- * Creates a new set with all elements that are present in either set
374
- */
375
- function union() {
376
- var e_1, _a, e_2, _b;
377
- var sets = [];
378
- for (var _i = 0; _i < arguments.length; _i++) {
379
- sets[_i] = arguments[_i];
380
- }
381
- var union = new Set();
382
- try {
383
- for (var sets_1 = __values(sets), sets_1_1 = sets_1.next(); !sets_1_1.done; sets_1_1 = sets_1.next()) {
384
- var set = sets_1_1.value;
385
- try {
386
- for (var _c = (e_2 = void 0, __values(Array.from(set))), _d = _c.next(); !_d.done; _d = _c.next()) {
387
- var item = _d.value;
388
- union.add(item);
389
- }
390
- }
391
- catch (e_2_1) { e_2 = { error: e_2_1 }; }
392
- finally {
393
- try {
394
- if (_d && !_d.done && (_b = _c.return)) _b.call(_c);
395
- }
396
- finally { if (e_2) throw e_2.error; }
397
- }
398
- }
399
- }
400
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
401
- finally {
402
- try {
403
- if (sets_1_1 && !sets_1_1.done && (_a = sets_1.return)) _a.call(sets_1);
404
- }
405
- finally { if (e_1) throw e_1.error; }
406
- }
407
- return union;
408
- }
409
-
410
- /**
411
- * The version of the Promptbook library
412
- */
413
- var PROMPTBOOK_VERSION = '0.52.0-2';
414
-
415
- /**
416
- * Parses the template and returns the list of all parameter names
417
- *
418
- * @param template the template with parameters in {curly} braces
419
- * @returns the list of parameter names
420
- */
421
- function extractParameters(template) {
422
- var e_1, _a;
423
- var matches = template.matchAll(/{\w+}/g);
424
- var parameterNames = new Set();
425
- try {
426
- for (var matches_1 = __values(matches), matches_1_1 = matches_1.next(); !matches_1_1.done; matches_1_1 = matches_1.next()) {
427
- var match = matches_1_1.value;
428
- var parameterName = match[0].slice(1, -1);
429
- parameterNames.add(parameterName);
430
- }
431
- }
432
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
433
- finally {
434
- try {
435
- if (matches_1_1 && !matches_1_1.done && (_a = matches_1.return)) _a.call(matches_1);
436
- }
437
- finally { if (e_1) throw e_1.error; }
438
- }
439
- return parameterNames;
440
- }
441
-
442
- /**
443
- * Parses the given script and returns the list of all used variables that are not defined in the script
444
- *
445
- * @param script from which to extract the variables
446
- * @returns the list of variable names
447
- * @throws {PromptbookSyntaxError} if the script is invalid
448
- */
449
- function extractVariables(script) {
450
- var variables = new Set();
451
- script = "(()=>{".concat(script, "})()");
452
- try {
453
- for (var i = 0; i < 100 /* <- TODO: This limit to configuration */; i++)
454
- try {
455
- eval(script);
456
- }
457
- catch (error) {
458
- if (!(error instanceof ReferenceError)) {
459
- throw error;
460
- }
461
- var undefinedName = error.message.split(' ')[0];
462
- /*
463
- Note: Remapping error
464
- From: [ReferenceError: thing is not defined],
465
- To: [Error: Parameter {thing} is not defined],
466
- */
467
- if (!undefinedName) {
468
- throw error;
469
- }
470
- if (script.includes(undefinedName + '(')) {
471
- script = "const ".concat(undefinedName, " = ()=>'';") + script;
472
- }
473
- else {
474
- variables.add(undefinedName);
475
- script = "const ".concat(undefinedName, " = '';") + script;
476
- }
477
- }
478
- }
479
- catch (error) {
480
- if (!(error instanceof Error)) {
481
- throw error;
482
- }
483
- throw new PromptbookSyntaxError(spaceTrim(function (block) { return "\n Can not extract variables from the script\n\n ".concat(block(error.name), ": ").concat(block(error.message), "\n "); }));
484
- }
485
- return variables;
486
- }
487
- /**
488
- * TODO: [🔣] Support for multiple languages - python, java,...
489
- */
490
-
491
- /**
492
- * Parses the prompt template and returns the set of all used parameters
493
- *
494
- * @param promptTemplate the template with used parameters
495
- * @returns the set of parameter names
496
- * @throws {PromptbookSyntaxError} if the script is invalid
497
- */
498
- function extractParametersFromPromptTemplate(promptTemplate) {
499
- var e_1, _a, e_2, _b;
500
- var parameterNames = new Set();
501
- try {
502
- for (var _c = __values(__spreadArray(__spreadArray(__spreadArray([], __read(extractParameters(promptTemplate.title)), false), __read(extractParameters(promptTemplate.description || '')), false), __read(extractParameters(promptTemplate.content)), false)), _d = _c.next(); !_d.done; _d = _c.next()) {
503
- var parameterName = _d.value;
504
- parameterNames.add(parameterName);
505
- }
506
- }
507
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
508
- finally {
509
- try {
510
- if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
511
- }
512
- finally { if (e_1) throw e_1.error; }
513
- }
514
- if (promptTemplate.executionType === 'SCRIPT') {
515
- try {
516
- for (var _e = __values(extractVariables(promptTemplate.content)), _f = _e.next(); !_f.done; _f = _e.next()) {
517
- var parameterName = _f.value;
518
- parameterNames.add(parameterName);
519
- }
520
- }
521
- catch (e_2_1) { e_2 = { error: e_2_1 }; }
522
- finally {
523
- try {
524
- if (_f && !_f.done && (_b = _e.return)) _b.call(_e);
525
- }
526
- finally { if (e_2) throw e_2.error; }
527
- }
528
- }
529
- return parameterNames;
530
- }
531
- /**
532
- * TODO: [🔣] If script require contentLanguage
533
- */
534
-
535
- /**
536
- * Execution type describes the way how the block is executed
537
- *
538
- * @see https://github.com/webgptorg/promptbook#execution-type
539
- */
540
- var ExecutionTypes = [
541
- 'PROMPT_TEMPLATE',
542
- 'SIMPLE_TEMPLATE',
543
- 'SCRIPT',
544
- 'PROMPT_DIALOG',
545
- // <- [🥻] Insert here when making new command
546
- ];
547
-
548
- /**
549
- * Units of text measurement
550
- */
551
- var EXPECTATION_UNITS = ['CHARACTERS', 'WORDS', 'SENTENCES', 'LINES', 'PARAGRAPHS', 'PAGES'];
552
- /**
553
- * TODO: [💝] Unite object for expecting amount and format - remove expectFormat
554
- * TODO: use one helper type> (string_prompt | string_javascript | string_markdown) & string_template
555
- * TODO: [👙][🧠] Just selecting gpt3 or gpt4 level of model
556
- */
557
-
558
- /**
559
- * Removes Markdown formatting tags from a string.
560
- *
561
- * @param {string} str - The string to remove Markdown tags from.
562
- * @returns {string} The input string with all Markdown tags removed.
563
- */
564
- function removeMarkdownFormatting(str) {
565
- // Remove bold formatting
566
- str = str.replace(/\*\*(.*?)\*\*/g, '$1');
567
- // Remove italic formatting
568
- str = str.replace(/\*(.*?)\*/g, '$1');
569
- // Remove code formatting
570
- str = str.replace(/`(.*?)`/g, '$1');
571
- return str;
572
- }
573
-
574
- /**
575
- * Function parseNumber will parse number from string
576
- *
577
- * Unlike Number.parseInt, Number.parseFloat it will never ever result in NaN
578
- * Note: it also works only with decimal numbers
357
+ * Unlike Number.parseInt, Number.parseFloat it will never ever result in NaN
358
+ * Note: it also works only with decimal numbers
579
359
  *
580
360
  * @returns parsed number
581
361
  * @throws {PromptbookSyntaxError} if the value is not a number
@@ -619,682 +399,23 @@ function parseNumber(value) {
619
399
  return numerator / denominator;
620
400
  }
621
401
  if (/^(NAN|NULL|NONE|UNDEFINED|ZERO|NO.*)$/.test(value)) {
622
- return 0;
623
- }
624
- if (value.includes('E')) {
625
- var _b = __read(value.split('E'), 2), significand = _b[0], exponent = _b[1];
626
- return parseNumber(significand) * Math.pow(10, parseNumber(exponent));
627
- }
628
- if (!/^[0-9.]+$/.test(value) || value.split('.').length > 2) {
629
- throw new PromptbookSyntaxError("Unable to parse number from \"".concat(originalValue, "\""));
630
- }
631
- var num = parseFloat(value);
632
- if (isNaN(num)) {
633
- throw new PromptbookSyntaxError("Unexpected NaN when parsing number from \"".concat(originalValue, "\""));
634
- }
635
- return num;
636
- }
637
- /**
638
- * TODO: Maybe use sth. like safe-eval in fraction/calculation case @see https://www.npmjs.com/package/safe-eval
639
- */
640
-
641
- /**
642
- * Parses one line of ul/ol to command
643
- *
644
- * @returns parsed command object
645
- * @throws {PromptbookSyntaxError} if the command is invalid
646
- *
647
- * @private within the promptbookStringToJson
648
- */
649
- function parseCommand(listItem) {
650
- var e_1, _a;
651
- if (listItem.includes('\n') || listItem.includes('\r')) {
652
- throw new PromptbookSyntaxError('Command can not contain new line characters:');
653
- }
654
- var type = listItem.trim();
655
- type = type.split('`').join('');
656
- type = type.split('"').join('');
657
- type = type.split("'").join('');
658
- type = type.split('~').join('');
659
- type = type.split('[').join('');
660
- type = type.split(']').join('');
661
- type = type.split('(').join('');
662
- type = type.split(')').join('');
663
- type = normalizeTo_SCREAMING_CASE(type);
664
- type = type.split('DIALOGUE').join('DIALOG');
665
- var listItemParts = listItem
666
- .split(' ')
667
- .map(function (part) { return part.trim(); })
668
- .filter(function (item) { return item !== ''; })
669
- .filter(function (item) { return !/^PTBK$/i.test(item); })
670
- .filter(function (item) { return !/^PROMPTBOOK$/i.test(item); })
671
- .map(removeMarkdownFormatting);
672
- if (type.startsWith('URL') ||
673
- type.startsWith('PTBK_URL') ||
674
- type.startsWith('PTBKURL') ||
675
- type.startsWith('PROMPTBOOK_URL') ||
676
- type.startsWith('PROMPTBOOKURL') ||
677
- type.startsWith('HTTPS')) {
678
- if (!(listItemParts.length === 2 || (listItemParts.length === 1 && type.startsWith('HTTPS')))) {
679
- throw new PromptbookSyntaxError(spaceTrim("\n Invalid PROMPTBOOK_URL command:\n\n - ".concat(listItem, "\n ")));
680
- }
681
- var promptbookUrlString = listItemParts.pop();
682
- var promptbookUrl = new URL(promptbookUrlString);
683
- if (promptbookUrl.protocol !== 'https:') {
684
- throw new PromptbookSyntaxError(spaceTrim("\n Invalid PROMPTBOOK_URL command:\n\n - ".concat(listItem, "\n\n Protocol must be HTTPS\n ")));
685
- }
686
- if (promptbookUrl.hash !== '') {
687
- throw new PromptbookSyntaxError(spaceTrim("\n Invalid PROMPTBOOK_URL command:\n\n - ".concat(listItem, "\n\n URL must not contain hash\n Hash is used for identification of the prompt template in the pipeline\n ")));
688
- }
689
- return {
690
- type: 'PROMPTBOOK_URL',
691
- promptbookUrl: promptbookUrl,
692
- };
693
- }
694
- else if (type.startsWith('PROMPTBOOK_VERSION') || type.startsWith('PTBK_VERSION')) {
695
- if (listItemParts.length !== 2) {
696
- throw new PromptbookSyntaxError(spaceTrim("\n Invalid PROMPTBOOK_VERSION command:\n\n - ".concat(listItem, "\n ")));
697
- }
698
- var promptbookVersion = listItemParts.pop();
699
- // TODO: Validate version
700
- return {
701
- type: 'PROMPTBOOK_VERSION',
702
- promptbookVersion: promptbookVersion,
703
- };
704
- }
705
- else if (type.startsWith('EXECUTE') ||
706
- type.startsWith('EXEC') ||
707
- type.startsWith('PROMPT_DIALOG') ||
708
- type.startsWith('SIMPLE_TEMPLATE')) {
709
- var executionTypes = ExecutionTypes.filter(function (executionType) { return type.includes(executionType); });
710
- if (executionTypes.length !== 1) {
711
- throw new PromptbookSyntaxError(spaceTrim(function (block) { return "\n Unknown execution type in command:\n\n - ".concat(listItem, "\n\n Supported execution types are:\n ").concat(block(ExecutionTypes.join(', ')), "\n "); }));
712
- }
713
- return {
714
- type: 'EXECUTE',
715
- executionType: executionTypes[0],
716
- };
717
- }
718
- else if (type.startsWith('MODEL')) {
719
- // TODO: Make this more elegant and dynamically
720
- if (type.startsWith('MODEL_VARIANT')) {
721
- if (type === 'MODEL_VARIANT_CHAT') {
722
- return {
723
- type: 'MODEL',
724
- key: 'modelVariant',
725
- value: 'CHAT',
726
- };
727
- }
728
- else if (type === 'MODEL_VARIANT_COMPLETION') {
729
- return {
730
- type: 'MODEL',
731
- key: 'modelVariant',
732
- value: 'COMPLETION',
733
- };
734
- }
735
- else {
736
- throw new PromptbookSyntaxError(spaceTrim(function (block) { return "\n Unknown model variant in command:\n\n - ".concat(listItem, "\n\n Supported variants are:\n ").concat(block(['CHAT', 'COMPLETION'].join(', ')), "\n "); }));
737
- }
738
- }
739
- if (type.startsWith('MODEL_NAME')) {
740
- return {
741
- type: 'MODEL',
742
- key: 'modelName',
743
- value: listItemParts.pop(),
744
- };
745
- }
746
- else {
747
- throw new PromptbookSyntaxError(spaceTrim(function (block) { return "\n Unknown model key in command:\n\n - ".concat(listItem, "\n\n Supported model keys are:\n ").concat(block(['variant', 'name'].join(', ')), "\n\n Example:\n\n - MODEL VARIANT Chat\n - MODEL NAME gpt-4\n "); }));
748
- }
749
- }
750
- else if (type.startsWith('PARAM') ||
751
- type.startsWith('INPUT_PARAM') ||
752
- type.startsWith('OUTPUT_PARAM') ||
753
- listItem.startsWith('{') ||
754
- listItem.startsWith('> {') /* <- Note: This is a bit hack to parse return parameters defined at the end of each section */) {
755
- var parametersMatch = listItem.match(/\{(?<parameterName>[a-z0-9_]+)\}[^\S\r\n]*(?<parameterDescription>.*)$/im);
756
- if (!parametersMatch || !parametersMatch.groups || !parametersMatch.groups.parameterName) {
757
- throw new PromptbookSyntaxError(spaceTrim("\n Invalid parameter in command:\n\n - ".concat(listItem, "\n ")));
758
- }
759
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
760
- var _b = parametersMatch.groups, parameterName = _b.parameterName, parameterDescription = _b.parameterDescription;
761
- if (parameterDescription && parameterDescription.match(/\{(?<parameterName>[a-z0-9_]+)\}/im)) {
762
- throw new PromptbookSyntaxError(spaceTrim("\n Parameter {".concat(parameterName, "} can not contain another parameter in description:\n\n - ").concat(listItem, "\n ")));
763
- }
764
- var isInput = type.startsWith('INPUT');
765
- var isOutput = type.startsWith('OUTPUT');
766
- if (listItem.startsWith('> {')) {
767
- isInput = false;
768
- isOutput = false;
769
- }
770
- return {
771
- type: 'PARAMETER',
772
- parameterName: parameterName,
773
- parameterDescription: parameterDescription.trim() || null,
774
- isInput: isInput,
775
- isOutput: isOutput,
776
- };
777
- }
778
- else if (type.startsWith('JOKER')) {
779
- if (listItemParts.length !== 2) {
780
- throw new PromptbookSyntaxError(spaceTrim("\n Invalid JOKER command:\n\n - ".concat(listItem, "\n ")));
781
- }
782
- var parametersMatch = (listItemParts.pop() || '').match(/^\{(?<parameterName>[a-z0-9_]+)\}$/im);
783
- if (!parametersMatch || !parametersMatch.groups || !parametersMatch.groups.parameterName) {
784
- throw new PromptbookSyntaxError(spaceTrim("\n Invalid parameter in command:\n\n - ".concat(listItem, "\n ")));
785
- }
786
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
787
- var parameterName = parametersMatch.groups.parameterName;
788
- return {
789
- type: 'JOKER',
790
- parameterName: parameterName,
791
- };
792
- }
793
- else if (type.startsWith('POSTPROCESS') || type.startsWith('POST_PROCESS')) {
794
- if (listItemParts.length !== 2) {
795
- throw new PromptbookSyntaxError(spaceTrim("\n Invalid POSTPROCESSING command:\n\n - ".concat(listItem, "\n ")));
796
- }
797
- var functionName = listItemParts.pop();
798
- return {
799
- type: 'POSTPROCESS',
800
- functionName: functionName,
801
- };
802
- }
803
- else if (type.startsWith('EXPECT_JSON')) {
804
- return {
805
- type: 'EXPECT_FORMAT',
806
- format: 'JSON',
807
- };
808
- // [🥤]
809
- }
810
- else if (type.startsWith('EXPECT')) {
811
- try {
812
- listItemParts.shift();
813
- var sign = void 0;
814
- var signRaw = listItemParts.shift();
815
- if (/^exact/i.test(signRaw)) {
816
- sign = 'EXACTLY';
817
- }
818
- else if (/^min/i.test(signRaw)) {
819
- sign = 'MINIMUM';
820
- }
821
- else if (/^max/i.test(signRaw)) {
822
- sign = 'MAXIMUM';
823
- }
824
- else {
825
- throw new PromptbookSyntaxError("Invalid sign \"".concat(signRaw, "\", expected EXACTLY, MIN or MAX"));
826
- }
827
- var amountRaw = listItemParts.shift();
828
- var amount = parseNumber(amountRaw);
829
- if (amount < 0) {
830
- throw new PromptbookSyntaxError('Amount must be positive number or zero');
831
- }
832
- if (amount !== Math.floor(amount)) {
833
- throw new PromptbookSyntaxError('Amount must be whole number');
834
- }
835
- var unitRaw = listItemParts.shift();
836
- var unit = undefined;
837
- try {
838
- for (var EXPECTATION_UNITS_1 = __values(EXPECTATION_UNITS), EXPECTATION_UNITS_1_1 = EXPECTATION_UNITS_1.next(); !EXPECTATION_UNITS_1_1.done; EXPECTATION_UNITS_1_1 = EXPECTATION_UNITS_1.next()) {
839
- var existingUnit = EXPECTATION_UNITS_1_1.value;
840
- var existingUnitText = existingUnit;
841
- existingUnitText = existingUnitText.substring(0, existingUnitText.length - 1);
842
- if (existingUnitText === 'CHARACTER') {
843
- existingUnitText = 'CHAR';
844
- }
845
- if (new RegExp("^".concat(existingUnitText.toLowerCase())).test(unitRaw.toLowerCase()) ||
846
- new RegExp("^".concat(unitRaw.toLowerCase())).test(existingUnitText.toLowerCase())) {
847
- if (unit !== undefined) {
848
- throw new PromptbookSyntaxError("Ambiguous unit \"".concat(unitRaw, "\""));
849
- }
850
- unit = existingUnit;
851
- }
852
- }
853
- }
854
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
855
- finally {
856
- try {
857
- if (EXPECTATION_UNITS_1_1 && !EXPECTATION_UNITS_1_1.done && (_a = EXPECTATION_UNITS_1.return)) _a.call(EXPECTATION_UNITS_1);
858
- }
859
- finally { if (e_1) throw e_1.error; }
860
- }
861
- if (unit === undefined) {
862
- throw new PromptbookSyntaxError("Invalid unit \"".concat(unitRaw, "\""));
863
- }
864
- return {
865
- type: 'EXPECT_AMOUNT',
866
- sign: sign,
867
- unit: unit,
868
- amount: amount,
869
- };
870
- }
871
- catch (error) {
872
- if (!(error instanceof Error)) {
873
- throw error;
874
- }
875
- throw new PromptbookSyntaxError(spaceTrim("\n Invalid EXPECT command; ".concat(error.message, ":\n\n - ").concat(listItem, "\n ")));
876
- }
877
- /*
878
- } else if (type.startsWith('__________________')) {
879
- // <- [🥻] Insert here when making new command
880
- */
881
- }
882
- else {
883
- throw new PromptbookSyntaxError(spaceTrim("\n Unknown command:\n\n - ".concat(listItem, "\n\n Supported commands are:\n - PROMPTBOOK_URL <url>\n - PROMPTBOOK_VERSION <version>\n - EXECUTE PROMPT TEMPLATE\n - EXECUTE SIMPLE TEMPLATE\n - SIMPLE TEMPLATE\n - EXECUTE SCRIPT\n - EXECUTE PROMPT_DIALOG'\n - PROMPT_DIALOG'\n - MODEL NAME <name>\n - MODEL VARIANT <\"Chat\"|\"Completion\">\n - INPUT PARAM {<name>} <description>\n - OUTPUT PARAM {<name>} <description>\n - POSTPROCESS `{functionName}`\n - JOKER {<name>}\n - EXPECT JSON\n - EXPECT <\"Exactly\"|\"Min\"|\"Max\"> <number> <\"Chars\"|\"Words\"|\"Sentences\"|\"Paragraphs\"|\"Pages\">\n\n ")));
884
- }
885
- }
886
-
887
- /**
888
- * Removes emojis from a string and fix whitespaces
889
- *
890
- * @param text with emojis
891
- * @returns text without emojis
892
- */
893
- function removeEmojis(text) {
894
- // Replace emojis (and also ZWJ sequence) with hyphens
895
- text = text.replace(/(\p{Extended_Pictographic})\p{Modifier_Symbol}/gu, '$1');
896
- text = text.replace(/(\p{Extended_Pictographic})[\u{FE00}-\u{FE0F}]/gu, '$1');
897
- text = text.replace(/(\p{Extended_Pictographic})(\u{200D}\p{Extended_Pictographic})*/gu, '$1');
898
- text = text.replace(/\p{Extended_Pictographic}/gu, '');
899
- return text;
900
- }
901
-
902
- /**
903
- * Function normalizes title to name which can be used as identifier
904
- */
905
- function titleToName(value) {
906
- value = removeEmojis(value);
907
- value = normalizeToKebabCase(value);
908
- // TODO: [🧠] Maybe warn or add some padding to short name which are not good identifiers
909
- return value;
910
- }
911
-
912
- /**
913
- * Parse promptbook from string format to JSON format
914
- *
915
- * @throws {PromptbookSyntaxError} if the promptbook string is not valid
916
- *
917
- * Note: This function does not validate logic of the pipeline only the syntax
918
- */
919
- function promptbookStringToJson(promptbookString) {
920
- var e_1, _a, e_2, _b;
921
- var promptbookJson = {
922
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
923
- title: undefined /* <- Note: Putting here placeholder to keep `title` on top at final JSON */,
924
- promptbookUrl: undefined /* <- Note: Putting here placeholder to keep `promptbookUrl` on top at final JSON */,
925
- promptbookVersion: PROMPTBOOK_VERSION,
926
- description: undefined /* <- Note: Putting here placeholder to keep `description` on top at final JSON */,
927
- parameters: [],
928
- promptTemplates: [],
929
- };
930
- // =============================================================
931
- // Note: 1️⃣ Normalization of the PROMPTBOOK string
932
- promptbookString = removeContentComments(promptbookString);
933
- promptbookString = promptbookString.replaceAll(/`\{(?<parameterName>[a-z0-9_]+)\}`/gi, '{$<parameterName>}');
934
- promptbookString = promptbookString.replaceAll(/`->\s+\{(?<parameterName>[a-z0-9_]+)\}`/gi, '-> {$<parameterName>}');
935
- // =============================================================
936
- ///Note: 2️⃣ Function for adding parameters
937
- var addParam = function (parameterCommand) {
938
- var parameterName = parameterCommand.parameterName, parameterDescription = parameterCommand.parameterDescription, isInput = parameterCommand.isInput, isOutput = parameterCommand.isOutput;
939
- var existingParameter = promptbookJson.parameters.find(function (parameter) { return parameter.name === parameterName; });
940
- if (existingParameter &&
941
- existingParameter.description &&
942
- existingParameter.description !== parameterDescription &&
943
- parameterDescription) {
944
- throw new PromptbookSyntaxError(spaceTrim(function (block) { return "\n Parameter {".concat(parameterName, "} is defined multiple times with different description.\n\n First definition:\n ").concat(block(existingParameter.description || '[undefined]'), "\n\n Second definition:\n ").concat(block(parameterDescription || '[undefined]'), "\n "); }));
945
- }
946
- if (existingParameter) {
947
- if (parameterDescription) {
948
- existingParameter.description = parameterDescription;
949
- }
950
- }
951
- else {
952
- promptbookJson.parameters.push({
953
- name: parameterName,
954
- description: parameterDescription || undefined,
955
- isInput: isInput,
956
- isOutput: isOutput,
957
- });
958
- }
959
- };
960
- // =============================================================
961
- // Note: 3️⃣ Parse the dynamic part - the template pipeline
962
- var markdownStructure = markdownToMarkdownStructure(promptbookString);
963
- var markdownStructureDeepness = countMarkdownStructureDeepness(markdownStructure);
964
- if (markdownStructureDeepness !== 2) {
965
- throw new PromptbookSyntaxError(spaceTrim("\n Invalid markdown structure.\n The markdown must have exactly 2 levels of headings (one top-level section and one section for each template).\n Now it has ".concat(markdownStructureDeepness, " levels of headings.\n ")));
966
- }
967
- promptbookJson.title = markdownStructure.title;
968
- // TODO: [1] DRY description
969
- var description = markdownStructure.content;
970
- // Note: Remove codeblocks
971
- description = description.split(/^```.*^```/gms).join('');
972
- //Note: Remove lists and return statement
973
- description = description.split(/^(?:(?:-)|(?:\d\))|(?:`?->))\s+.*$/gm).join('');
974
- description = spaceTrim(description);
975
- if (description === '') {
976
- description = undefined;
977
- }
978
- promptbookJson.description = description;
979
- var defaultModelRequirements = {};
980
- var listItems = extractAllListItemsFromMarkdown(markdownStructure.content);
981
- try {
982
- for (var listItems_1 = __values(listItems), listItems_1_1 = listItems_1.next(); !listItems_1_1.done; listItems_1_1 = listItems_1.next()) {
983
- var listItem = listItems_1_1.value;
984
- var command = parseCommand(listItem);
985
- switch (command.type) {
986
- case 'PROMPTBOOK_URL':
987
- promptbookJson.promptbookUrl = command.promptbookUrl.href;
988
- break;
989
- case 'PROMPTBOOK_VERSION':
990
- promptbookJson.promptbookVersion = command.promptbookVersion;
991
- break;
992
- case 'MODEL':
993
- defaultModelRequirements[command.key] = command.value;
994
- break;
995
- case 'PARAMETER':
996
- addParam(command);
997
- break;
998
- default:
999
- throw new PromptbookSyntaxError("Command ".concat(command.type, " is not allowed in the head of the promptbook ONLY at the prompt template block"));
1000
- }
1001
- }
1002
- }
1003
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
1004
- finally {
1005
- try {
1006
- if (listItems_1_1 && !listItems_1_1.done && (_a = listItems_1.return)) _a.call(listItems_1);
1007
- }
1008
- finally { if (e_1) throw e_1.error; }
1009
- }
1010
- var _loop_1 = function (section) {
1011
- var e_3, _e;
1012
- // TODO: Parse prompt template description (the content out of the codeblock and lists)
1013
- var templateModelRequirements = __assign({}, defaultModelRequirements);
1014
- var listItems_3 = extractAllListItemsFromMarkdown(section.content);
1015
- var dependentParameterNames = new Set();
1016
- var executionType = 'PROMPT_TEMPLATE';
1017
- var jokers = [];
1018
- var postprocessing = [];
1019
- var expectAmount = {};
1020
- var expectFormat = undefined;
1021
- var isExecutionTypeChanged = false;
1022
- try {
1023
- for (var listItems_2 = (e_3 = void 0, __values(listItems_3)), listItems_2_1 = listItems_2.next(); !listItems_2_1.done; listItems_2_1 = listItems_2.next()) {
1024
- var listItem = listItems_2_1.value;
1025
- var command = parseCommand(listItem);
1026
- switch (command.type) {
1027
- case 'JOKER':
1028
- jokers.push(command.parameterName);
1029
- dependentParameterNames.add(command.parameterName);
1030
- break;
1031
- case 'EXECUTE':
1032
- if (isExecutionTypeChanged) {
1033
- throw new PromptbookSyntaxError('Execution type is already defined in the prompt template. It can be defined only once.');
1034
- }
1035
- executionType = command.executionType;
1036
- isExecutionTypeChanged = true;
1037
- break;
1038
- case 'MODEL':
1039
- templateModelRequirements[command.key] = command.value;
1040
- break;
1041
- case 'PARAMETER':
1042
- // Note: This is just for detecting resulitng parameter name
1043
- addParam(command);
1044
- break;
1045
- case 'POSTPROCESS':
1046
- postprocessing.push(command.functionName);
1047
- break;
1048
- case 'EXPECT_AMOUNT':
1049
- // eslint-disable-next-line no-case-declarations
1050
- var unit = command.unit.toLowerCase();
1051
- expectAmount[unit] = expectAmount[unit] || {};
1052
- if (command.sign === 'MINIMUM' || command.sign === 'EXACTLY') {
1053
- if (expectAmount[unit].min !== undefined) {
1054
- throw new PromptbookSyntaxError("Already defined minumum ".concat(expectAmount[unit].min, " ").concat(command.unit.toLowerCase(), ", now trying to redefine it to ").concat(command.amount));
1055
- }
1056
- expectAmount[unit].min = command.amount;
1057
- } /* not else */
1058
- if (command.sign === 'MAXIMUM' || command.sign === 'EXACTLY') {
1059
- if (expectAmount[unit].max !== undefined) {
1060
- throw new PromptbookSyntaxError("Already defined maximum ".concat(expectAmount[unit].max, " ").concat(command.unit.toLowerCase(), ", now trying to redefine it to ").concat(command.amount));
1061
- }
1062
- expectAmount[unit].max = command.amount;
1063
- }
1064
- break;
1065
- case 'EXPECT_FORMAT':
1066
- if (expectFormat !== undefined && command.format !== expectFormat) {
1067
- throw new PromptbookSyntaxError("Expect format is already defined to \"".concat(expectFormat, "\". Now you try to redefine it by \"").concat(command.format, "\"."));
1068
- }
1069
- expectFormat = command.format;
1070
- break;
1071
- default:
1072
- throw new PromptbookSyntaxError("Command ".concat(command.type, " is not allowed in the block of the prompt template ONLY at the head of the promptbook"));
1073
- }
1074
- }
1075
- }
1076
- catch (e_3_1) { e_3 = { error: e_3_1 }; }
1077
- finally {
1078
- try {
1079
- if (listItems_2_1 && !listItems_2_1.done && (_e = listItems_2.return)) _e.call(listItems_2);
1080
- }
1081
- finally { if (e_3) throw e_3.error; }
1082
- }
1083
- var _f = extractOneBlockFromMarkdown(section.content), language = _f.language, content = _f.content;
1084
- if (executionType === 'SCRIPT') {
1085
- if (!language) {
1086
- throw new PromptbookSyntaxError('You must specify the language of the script in the prompt template');
1087
- }
1088
- else if (!SUPPORTED_SCRIPT_LANGUAGES.includes(language)) {
1089
- throw new PromptbookSyntaxError(spaceTrim(function (block) { return "\n Script language ".concat(language, " is not supported.\n\n Supported languages are:\n ").concat(block(SUPPORTED_SCRIPT_LANGUAGES.join(', ')), "\n\n "); }));
1090
- }
1091
- }
1092
- var lastLine = section.content.split('\n').pop();
1093
- var match = /^->\s*\{(?<resultingParamName>[a-z0-9_]+)\}/im.exec(lastLine);
1094
- if (!match || match.groups === undefined || match.groups.resultingParamName === undefined) {
1095
- throw new PromptbookSyntaxError(spaceTrim(function (block) { return "\n Invalid template - each section must end with \"-> {...}\"\n\n Invalid section:\n ".concat(block(
1096
- // TODO: Show code of invalid sections each time + DRY
1097
- section.content
1098
- .split('\n')
1099
- .map(function (line) { return "> ".concat(line); })
1100
- .join('\n')), "\n "); }));
1101
- }
1102
- var resultingParameterName = match.groups.resultingParamName;
1103
- // TODO: [1] DRY description
1104
- var description_1 = section.content;
1105
- // Note: Remove codeblocks
1106
- description_1 = description_1.split(/^```.*^```/gms).join('');
1107
- //Note: Remove lists and return statement
1108
- description_1 = description_1.split(/^(?:(?:-)|(?:\d\))|(?:`?->))\s+.*$/gm).join('');
1109
- description_1 = spaceTrim(description_1);
1110
- if (description_1 === '') {
1111
- description_1 = undefined;
1112
- }
1113
- if (Object.keys(jokers).length === 0) {
1114
- jokers = undefined;
1115
- }
1116
- if (Object.keys(expectAmount).length === 0) {
1117
- expectAmount = undefined;
1118
- }
1119
- if (Object.keys(postprocessing).length === 0) {
1120
- postprocessing = undefined;
1121
- }
1122
- dependentParameterNames = union(dependentParameterNames, extractParametersFromPromptTemplate(__assign(__assign({}, section), { description: description_1, executionType: executionType, content: content })));
1123
- promptbookJson.promptTemplates.push({
1124
- name: titleToName(section.title),
1125
- title: section.title,
1126
- description: description_1,
1127
- dependentParameterNames: Array.from(dependentParameterNames),
1128
- executionType: executionType,
1129
- jokers: jokers,
1130
- postprocessing: postprocessing,
1131
- expectations: expectAmount,
1132
- expectFormat: expectFormat,
1133
- modelRequirements: templateModelRequirements,
1134
- contentLanguage: executionType === 'SCRIPT' ? language : undefined,
1135
- content: content,
1136
- resultingParameterName: resultingParameterName,
1137
- });
1138
- };
1139
- try {
1140
- for (var _c = __values(markdownStructure.sections), _d = _c.next(); !_d.done; _d = _c.next()) {
1141
- var section = _d.value;
1142
- _loop_1(section);
1143
- }
1144
- }
1145
- catch (e_2_1) { e_2 = { error: e_2_1 }; }
1146
- finally {
1147
- try {
1148
- if (_d && !_d.done && (_b = _c.return)) _b.call(_c);
1149
- }
1150
- finally { if (e_2) throw e_2.error; }
1151
- }
1152
- // =============================================================
1153
- return promptbookJson;
1154
- }
1155
- /**
1156
- * TODO: Report here line/column of error
1157
- * TODO: Use spaceTrim more effectively
1158
- * TODO: [🧠] Parameter flags - isInput, isOutput, isInternal
1159
- */
1160
-
1161
- /**
1162
- * Add or modify an auto-generated section in a markdown file
1163
- *
1164
- * @private within the library
1165
- */
1166
- function addAutoGeneratedSection(content, options) {
1167
- var sectionName = options.sectionName, sectionContent = options.sectionContent;
1168
- var warningLine = "<!-- \u26A0\uFE0F WARNING: This section was auto-generated -->";
1169
- var sectionRegex = new RegExp("<!--".concat(sectionName, "-->([\\s\\S]*?)<!--/").concat(sectionName, "-->"), 'g');
1170
- var sectionMatch = content.match(sectionRegex);
1171
- if (sectionMatch) {
1172
- return content.replace(sectionRegex, spaceTrim(function (block) { return "\n <!--".concat(sectionName, "-->\n ").concat(block(warningLine), "\n ").concat(block(sectionContent), "\n <!--/").concat(sectionName, "-->\n "); }));
1173
- }
1174
- var placeForSection = removeContentComments(content).match(/^##.*$/im);
1175
- if (!placeForSection) {
1176
- throw new Error("No place where to put the section <!--".concat(sectionName, "-->"));
1177
- }
1178
- var _a = __read(placeForSection, 1), heading = _a[0];
1179
- return content.replace(heading, "<!--".concat(sectionName, "-->\n").concat(warningLine, "\n").concat(sectionContent, "\n<!--/").concat(sectionName, "-->\n\n").concat(heading));
1180
- }
1181
-
1182
- /**
1183
- * Prettify the html code
1184
- *
1185
- * @param content raw html code
1186
- * @returns formatted html code
1187
- */
1188
- function prettifyMarkdown(content) {
1189
- try {
1190
- return format(content, {
1191
- parser: 'markdown',
1192
- plugins: [parserHtml],
1193
- // TODO: DRY - make some import or auto-copy of .prettierrc
1194
- endOfLine: 'lf',
1195
- tabWidth: 4,
1196
- singleQuote: true,
1197
- trailingComma: 'all',
1198
- arrowParens: 'always',
1199
- printWidth: 120,
1200
- htmlWhitespaceSensitivity: 'ignore',
1201
- jsxBracketSameLine: false,
1202
- bracketSpacing: true,
1203
- });
1204
- }
1205
- catch (error) {
1206
- console.error('There was an error with prettifying the markdown, using the original as the fallback', {
1207
- error: error,
1208
- html: content,
1209
- });
1210
- return content;
1211
- }
1212
- }
1213
-
1214
- /**
1215
- * Creates a Mermaid graph based on the promptbook
1216
- *
1217
- * Note: The result is not wrapped in a Markdown code block
1218
- */
1219
- function renderPromptbookMermaid(promptbookJson, options) {
1220
- var _a = (options || {}).linkPromptTemplate, linkPromptTemplate = _a === void 0 ? function () { return null; } : _a;
1221
- var parameterNameToTemplateName = function (parameterName) {
1222
- var parameter = promptbookJson.parameters.find(function (parameter) { return parameter.name === parameterName; });
1223
- if (!parameter) {
1224
- throw new UnexpectedError("Could not find {".concat(parameterName, "}"));
1225
- }
1226
- if (parameter.isInput) {
1227
- return 'input';
1228
- }
1229
- var template = promptbookJson.promptTemplates.find(function (template) { return template.resultingParameterName === parameterName; });
1230
- if (!template) {
1231
- throw new Error("Could not find template for {".concat(parameterName, "}"));
1232
- }
1233
- return normalizeTo_camelCase('template-' + titleToName(template.title));
1234
- };
1235
- var promptbookMermaid = spaceTrim(function (block) { return "\n\n %% \uD83D\uDD2E Tip: Open this on GitHub or in the VSCode website to see the Mermaid graph visually\n\n flowchart LR\n subgraph \"".concat(promptbookJson.title, "\"\n\n direction TB\n\n input((Input)):::input\n ").concat(block(promptbookJson.promptTemplates
1236
- .flatMap(function (_a) {
1237
- var title = _a.title, dependentParameterNames = _a.dependentParameterNames, resultingParameterName = _a.resultingParameterName;
1238
- return __spreadArray([
1239
- "".concat(parameterNameToTemplateName(resultingParameterName), "(\"").concat(title, "\")")
1240
- ], __read(dependentParameterNames.map(function (dependentParameterName) {
1241
- return "".concat(parameterNameToTemplateName(dependentParameterName), "--\"{").concat(dependentParameterName, "}\"-->").concat(parameterNameToTemplateName(resultingParameterName));
1242
- })), false);
1243
- })
1244
- .join('\n')), "\n\n ").concat(block(promptbookJson.parameters
1245
- .filter(function (_a) {
1246
- var isOutput = _a.isOutput;
1247
- return isOutput;
1248
- })
1249
- .map(function (_a) {
1250
- var name = _a.name;
1251
- return "".concat(parameterNameToTemplateName(name), "--\"{").concat(name, "}\"-->output");
1252
- })
1253
- .join('\n')), "\n output((Output)):::output\n\n ").concat(block(promptbookJson.promptTemplates
1254
- .map(function (promptTemplate) {
1255
- var link = linkPromptTemplate(promptTemplate);
1256
- if (link === null) {
1257
- return '';
1258
- }
1259
- var href = link.href, title = link.title;
1260
- var templateName = parameterNameToTemplateName(promptTemplate.resultingParameterName);
1261
- return "click ".concat(templateName, " href \"").concat(href, "\" \"").concat(title, "\";");
1262
- })
1263
- .filter(function (line) { return line !== ''; })
1264
- .join('\n')), "\n\n classDef input color: grey;\n classDef output color: grey;\n\n end;\n\n "); });
1265
- return promptbookMermaid;
1266
- }
1267
- /**
1268
- * TODO: Maybe use some Mermaid library instead of string templating
1269
- * TODO: [🕌] When more than 2 functionalities, split into separate functions
1270
- */
1271
-
1272
- /**
1273
- * Prettyfies Promptbook string and adds Mermaid graph
1274
- */
1275
- function prettifyPromptbookString(promptbookString, options) {
1276
- var isGraphAdded = options.isGraphAdded, isPrettifyed = options.isPrettifyed;
1277
- if (isGraphAdded) {
1278
- var promptbookJson = promptbookStringToJson(promptbookString);
1279
- var promptbookMermaid_1 = renderPromptbookMermaid(promptbookJson, {
1280
- linkPromptTemplate: function (promptTemplate) {
1281
- return { href: "#".concat(promptTemplate.name), title: promptTemplate.title };
1282
- },
1283
- });
1284
- var promptbookMermaidBlock = spaceTrim(function (block) { return "\n ```mermaid\n ".concat(block(promptbookMermaid_1), "\n ```\n "); });
1285
- promptbookString = addAutoGeneratedSection(promptbookString, {
1286
- sectionName: 'Graph',
1287
- sectionContent: promptbookMermaidBlock,
1288
- });
402
+ return 0;
403
+ }
404
+ if (value.includes('E')) {
405
+ var _b = __read(value.split('E'), 2), significand = _b[0], exponent = _b[1];
406
+ return parseNumber(significand) * Math.pow(10, parseNumber(exponent));
407
+ }
408
+ if (!/^[0-9.]+$/.test(value) || value.split('.').length > 2) {
409
+ throw new PromptbookSyntaxError("Unable to parse number from \"".concat(originalValue, "\""));
1289
410
  }
1290
- if (isPrettifyed) {
1291
- promptbookString = prettifyMarkdown(promptbookString);
411
+ var num = parseFloat(value);
412
+ if (isNaN(num)) {
413
+ throw new PromptbookSyntaxError("Unexpected NaN when parsing number from \"".concat(originalValue, "\""));
1292
414
  }
1293
- return promptbookString;
415
+ return num;
1294
416
  }
1295
417
  /**
1296
- * TODO: Maybe use some Mermaid library instead of string templating
1297
- * TODO: [🕌] When more than 2 functionalities, split into separate functions
418
+ * TODO: Maybe use sth. like safe-eval in fraction/calculation case @see https://www.npmjs.com/package/safe-eval
1298
419
  */
1299
420
 
1300
421
  /**
@@ -1368,60 +489,159 @@ function renameParameter(options) {
1368
489
  }
1369
490
 
1370
491
  /**
1371
- * This error indicates errors during the execution of the promptbook
492
+ * Async version of Array.forEach
493
+ *
494
+ * @param array - Array to iterate over
495
+ * @param options - Options for the function
496
+ * @param callbackfunction - Function to call for each item
497
+ */
498
+ function forEachAsync(array, options, callbackfunction) {
499
+ return __awaiter(this, void 0, void 0, function () {
500
+ var _a, inParallelCount, index, runningTasks, tasks, _loop_1, _b, _c, item, e_1_1;
501
+ var e_1, _d;
502
+ return __generator(this, function (_e) {
503
+ switch (_e.label) {
504
+ case 0:
505
+ _a = options.inParallelCount, inParallelCount = _a === void 0 ? Infinity : _a;
506
+ index = 0;
507
+ runningTasks = [];
508
+ tasks = [];
509
+ _loop_1 = function (item) {
510
+ var currentIndex, task;
511
+ return __generator(this, function (_f) {
512
+ switch (_f.label) {
513
+ case 0:
514
+ currentIndex = index++;
515
+ task = callbackfunction(item, currentIndex, array);
516
+ tasks.push(task);
517
+ runningTasks.push(task);
518
+ /* not await */ Promise.resolve(task).then(function () {
519
+ runningTasks = runningTasks.filter(function (t) { return t !== task; });
520
+ });
521
+ if (!(inParallelCount < runningTasks.length)) return [3 /*break*/, 2];
522
+ return [4 /*yield*/, Promise.race(runningTasks)];
523
+ case 1:
524
+ _f.sent();
525
+ _f.label = 2;
526
+ case 2: return [2 /*return*/];
527
+ }
528
+ });
529
+ };
530
+ _e.label = 1;
531
+ case 1:
532
+ _e.trys.push([1, 6, 7, 8]);
533
+ _b = __values(array), _c = _b.next();
534
+ _e.label = 2;
535
+ case 2:
536
+ if (!!_c.done) return [3 /*break*/, 5];
537
+ item = _c.value;
538
+ return [5 /*yield**/, _loop_1(item)];
539
+ case 3:
540
+ _e.sent();
541
+ _e.label = 4;
542
+ case 4:
543
+ _c = _b.next();
544
+ return [3 /*break*/, 2];
545
+ case 5: return [3 /*break*/, 8];
546
+ case 6:
547
+ e_1_1 = _e.sent();
548
+ e_1 = { error: e_1_1 };
549
+ return [3 /*break*/, 8];
550
+ case 7:
551
+ try {
552
+ if (_c && !_c.done && (_d = _b.return)) _d.call(_b);
553
+ }
554
+ finally { if (e_1) throw e_1.error; }
555
+ return [7 /*endfinally*/];
556
+ case 8: return [4 /*yield*/, Promise.all(tasks)];
557
+ case 9:
558
+ _e.sent();
559
+ return [2 /*return*/];
560
+ }
561
+ });
562
+ });
563
+ }
564
+
565
+ /**
566
+ * The maximum number of iterations for a loops
567
+ */
568
+ var LOOP_LIMIT = 1000;
569
+
570
+ /**
571
+ * This error occurs during the parameter replacement in the template
572
+ *
573
+ * Note: This is a kindof subtype of PromptbookExecutionError because it occurs during the execution of the pipeline
1372
574
  */
1373
- var PromptbookExecutionError = /** @class */ (function (_super) {
1374
- __extends(PromptbookExecutionError, _super);
1375
- function PromptbookExecutionError(message) {
575
+ var TemplateError = /** @class */ (function (_super) {
576
+ __extends(TemplateError, _super);
577
+ function TemplateError(message) {
1376
578
  var _this = _super.call(this, message) || this;
1377
- _this.name = 'PromptbookExecutionError';
1378
- Object.setPrototypeOf(_this, PromptbookExecutionError.prototype);
579
+ _this.name = 'TemplateError';
580
+ Object.setPrototypeOf(_this, TemplateError.prototype);
1379
581
  return _this;
1380
582
  }
1381
- return PromptbookExecutionError;
583
+ return TemplateError;
1382
584
  }(Error));
1383
585
 
1384
586
  /**
1385
- * Asserts that the execution of a promptnook is successful
587
+ * Replaces parameters in template with values from parameters object
588
+ *
589
+ * @param template the template with parameters in {curly} braces
590
+ * @param parameters the object with parameters
591
+ * @returns the template with replaced parameters
592
+ * @throws {TemplateError} if parameter is not defined, not closed, or not opened
1386
593
  *
1387
- * @param executionResult - The partial result of the promptnook execution
1388
- * @throws {PromptbookExecutionError} If the execution is not successful or if multiple errors occurred
594
+ * @private within the createPromptbookExecutor
1389
595
  */
1390
- function assertsExecutionSuccessful(executionResult) {
1391
- var isSuccessful = executionResult.isSuccessful, errors = executionResult.errors;
1392
- if (isSuccessful === true) {
1393
- return;
1394
- }
1395
- if (errors.length === 0) {
1396
- throw new PromptbookExecutionError("Promptnook Execution failed because of unknown reason");
596
+ function replaceParameters(template, parameters) {
597
+ var replacedTemplate = template;
598
+ var match;
599
+ var loopLimit = LOOP_LIMIT;
600
+ var _loop_1 = function () {
601
+ if (loopLimit-- < 0) {
602
+ throw new UnexpectedError('Loop limit reached during parameters replacement in `replaceParameters`');
603
+ }
604
+ var precol = match.groups.precol;
605
+ var parameterName = match.groups.parameterName;
606
+ if (parameterName === '') {
607
+ return "continue";
608
+ }
609
+ if (parameterName.indexOf('{') !== -1 || parameterName.indexOf('}') !== -1) {
610
+ throw new TemplateError('Parameter is already opened or not closed');
611
+ }
612
+ if (parameters[parameterName] === undefined) {
613
+ throw new TemplateError("Parameter {".concat(parameterName, "} is not defined"));
614
+ }
615
+ var parameterValue = parameters[parameterName];
616
+ if (parameterValue === undefined) {
617
+ throw new TemplateError("Parameter {".concat(parameterName, "} is not defined"));
618
+ }
619
+ parameterValue = parameterValue.toString();
620
+ if (parameterValue.includes('\n') && /^\s*\W{0,3}\s*$/.test(precol)) {
621
+ parameterValue = parameterValue
622
+ .split('\n')
623
+ .map(function (line, index) { return (index === 0 ? line : "".concat(precol).concat(line)); })
624
+ .join('\n');
625
+ }
626
+ replacedTemplate =
627
+ replacedTemplate.substring(0, match.index + precol.length) +
628
+ parameterValue +
629
+ replacedTemplate.substring(match.index + precol.length + parameterName.length + 2);
630
+ };
631
+ while ((match = /^(?<precol>.*){(?<parameterName>\w+)}(.*)/m /* <- Not global */
632
+ .exec(replacedTemplate))) {
633
+ _loop_1();
1397
634
  }
1398
- else if (errors.length === 1) {
1399
- throw errors[0];
635
+ // [💫] Check if there are parameters that are not closed properly
636
+ if (/{\w+$/.test(replacedTemplate)) {
637
+ throw new TemplateError('Parameter is not closed');
1400
638
  }
1401
- else {
1402
- throw new PromptbookExecutionError(spaceTrim(function (block) { return "\n Multiple errors occurred during promptnook execution\n\n ".concat(block(errors.map(function (error) { return '- ' + error.message; }).join('\n')), "\n "); }));
639
+ // [💫] Check if there are parameters that are not opened properly
640
+ if (/^\w+}/.test(replacedTemplate)) {
641
+ throw new TemplateError('Parameter is not opened');
1403
642
  }
643
+ return replacedTemplate;
1404
644
  }
1405
- /**
1406
- * TODO: [🧠] Can this return type be better typed than void
1407
- */
1408
-
1409
- /**
1410
- * This error occurs when some expectation is not met in the execution of the pipeline
1411
- *
1412
- * @private Always catched and rethrown as `PromptbookExecutionError`
1413
- * Note: This is a kindof subtype of PromptbookExecutionError
1414
- */
1415
- var ExpectError = /** @class */ (function (_super) {
1416
- __extends(ExpectError, _super);
1417
- function ExpectError(message) {
1418
- var _this = _super.call(this, message) || this;
1419
- _this.name = 'ExpectError';
1420
- Object.setPrototypeOf(_this, ExpectError.prototype);
1421
- return _this;
1422
- }
1423
- return ExpectError;
1424
- }(Error));
1425
645
 
1426
646
  /**
1427
647
  * Counts number of characters in the text
@@ -1704,518 +924,222 @@ for (var i = 0; i < defaultDiacriticsRemovalMap.length; i++) {
1704
924
  }
1705
925
  // <- TODO: [🍓] Put to maker function to save execution time if not needed
1706
926
  /*
1707
- @see https://stackoverflow.com/questions/990904/remove-accents-diacritics-in-a-string-in-javascript
1708
- Licensed under the Apache License, Version 2.0 (the "License");
1709
- you may not use this file except in compliance with the License.
1710
- You may obtain a copy of the License at
1711
-
1712
- http://www.apache.org/licenses/LICENSE-2.0
1713
-
1714
- Unless required by applicable law or agreed to in writing, software
1715
- distributed under the License is distributed on an "AS IS" BASIS,
1716
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1717
- See the License for the specific language governing permissions and
1718
- limitations under the License.
1719
- */
1720
-
1721
- /**
1722
- *
1723
- */
1724
- function removeDiacritics(input) {
1725
- /*eslint no-control-regex: "off"*/
1726
- return input.replace(/[^\u0000-\u007E]/g, function (a) {
1727
- return DIACRITIC_VARIANTS_LETTERS[a] || a;
1728
- });
1729
- }
1730
-
1731
- /**
1732
- * Counts number of words in the text
1733
- */
1734
- function countWords(text) {
1735
- text = text.replace(/[\p{Extended_Pictographic}]/gu, 'a');
1736
- text = removeDiacritics(text);
1737
- return text.split(/[^a-zа-я0-9]+/i).filter(function (word) { return word.length > 0; }).length;
1738
- }
1739
-
1740
- /**
1741
- * Index of all counter functions
1742
- */
1743
- var CountUtils = {
1744
- CHARACTERS: countCharacters,
1745
- WORDS: countWords,
1746
- SENTENCES: countSentences,
1747
- PARAGRAPHS: countParagraphs,
1748
- LINES: countLines,
1749
- PAGES: countPages,
1750
- };
1751
-
1752
- /**
1753
- * Function checkExpectations will check if the expectations on given value are met
1754
- *
1755
- * Note: There are two simmilar functions:
1756
- * - `checkExpectations` which throws an error if the expectations are not met
1757
- * - `isPassingExpectations` which returns a boolean
1758
- *
1759
- * @throws {ExpectError} if the expectations are not met
1760
- * @returns {void} Nothing
1761
- */
1762
- function checkExpectations(expectations, value) {
1763
- var e_1, _a;
1764
- try {
1765
- for (var _b = __values(Object.entries(expectations)), _c = _b.next(); !_c.done; _c = _b.next()) {
1766
- var _d = __read(_c.value, 2), unit = _d[0], _e = _d[1], max = _e.max, min = _e.min;
1767
- var amount = CountUtils[unit.toUpperCase()](value);
1768
- if (min && amount < min) {
1769
- throw new ExpectError("Expected at least ".concat(min, " ").concat(unit, " but got ").concat(amount));
1770
- } /* not else */
1771
- if (max && amount > max) {
1772
- throw new ExpectError("Expected at most ".concat(max, " ").concat(unit, " but got ").concat(amount));
1773
- }
1774
- }
1775
- }
1776
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
1777
- finally {
1778
- try {
1779
- if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
1780
- }
1781
- finally { if (e_1) throw e_1.error; }
1782
- }
1783
- }
1784
- /**
1785
- * Function checkExpectations will check if the expectations on given value are met
1786
- *
1787
- * Note: There are two simmilar functions:
1788
- * - `checkExpectations` which throws an error if the expectations are not met
1789
- * - `isPassingExpectations` which returns a boolean
1790
- *
1791
- * @returns {boolean} True if the expectations are met
1792
- */
1793
- function isPassingExpectations(expectations, value) {
1794
- try {
1795
- checkExpectations(expectations, value);
1796
- return true;
1797
- }
1798
- catch (error) {
1799
- if (!(error instanceof ExpectError)) {
1800
- throw error;
1801
- }
1802
- return false;
1803
- }
1804
- }
1805
- /**
1806
- * TODO: [💝] Unite object for expecting amount and format
1807
- */
1808
-
1809
- /**
1810
- * This error occurs during the parameter replacement in the template
1811
- *
1812
- * Note: This is a kindof subtype of PromptbookExecutionError because it occurs during the execution of the pipeline
1813
- */
1814
- var TemplateError = /** @class */ (function (_super) {
1815
- __extends(TemplateError, _super);
1816
- function TemplateError(message) {
1817
- var _this = _super.call(this, message) || this;
1818
- _this.name = 'TemplateError';
1819
- Object.setPrototypeOf(_this, TemplateError.prototype);
1820
- return _this;
1821
- }
1822
- return TemplateError;
1823
- }(Error));
1824
-
1825
- /**
1826
- * Replaces parameters in template with values from parameters object
1827
- *
1828
- * @param template the template with parameters in {curly} braces
1829
- * @param parameters the object with parameters
1830
- * @returns the template with replaced parameters
1831
- * @throws {TemplateError} if parameter is not defined, not closed, or not opened
1832
- *
1833
- * @private within the createPromptbookExecutor
1834
- */
1835
- function replaceParameters(template, parameters) {
1836
- var replacedTemplate = template;
1837
- var match;
1838
- var loopLimit = LOOP_LIMIT;
1839
- var _loop_1 = function () {
1840
- if (loopLimit-- < 0) {
1841
- throw new UnexpectedError('Loop limit reached during parameters replacement in `replaceParameters`');
1842
- }
1843
- var precol = match.groups.precol;
1844
- var parameterName = match.groups.parameterName;
1845
- if (parameterName === '') {
1846
- return "continue";
1847
- }
1848
- if (parameterName.indexOf('{') !== -1 || parameterName.indexOf('}') !== -1) {
1849
- throw new TemplateError('Parameter is already opened or not closed');
1850
- }
1851
- if (parameters[parameterName] === undefined) {
1852
- throw new TemplateError("Parameter {".concat(parameterName, "} is not defined"));
1853
- }
1854
- var parameterValue = parameters[parameterName];
1855
- if (parameterValue === undefined) {
1856
- throw new TemplateError("Parameter {".concat(parameterName, "} is not defined"));
1857
- }
1858
- parameterValue = parameterValue.toString();
1859
- if (parameterValue.includes('\n') && /^\s*\W{0,3}\s*$/.test(precol)) {
1860
- parameterValue = parameterValue
1861
- .split('\n')
1862
- .map(function (line, index) { return (index === 0 ? line : "".concat(precol).concat(line)); })
1863
- .join('\n');
1864
- }
1865
- replacedTemplate =
1866
- replacedTemplate.substring(0, match.index + precol.length) +
1867
- parameterValue +
1868
- replacedTemplate.substring(match.index + precol.length + parameterName.length + 2);
1869
- };
1870
- while ((match = /^(?<precol>.*){(?<parameterName>\w+)}(.*)/m /* <- Not global */
1871
- .exec(replacedTemplate))) {
1872
- _loop_1();
1873
- }
1874
- // [💫] Check if there are parameters that are not closed properly
1875
- if (/{\w+$/.test(replacedTemplate)) {
1876
- throw new TemplateError('Parameter is not closed');
1877
- }
1878
- // [💫] Check if there are parameters that are not opened properly
1879
- if (/^\w+}/.test(replacedTemplate)) {
1880
- throw new TemplateError('Parameter is not opened');
1881
- }
1882
- return replacedTemplate;
1883
- }
927
+ @see https://stackoverflow.com/questions/990904/remove-accents-diacritics-in-a-string-in-javascript
928
+ Licensed under the Apache License, Version 2.0 (the "License");
929
+ you may not use this file except in compliance with the License.
930
+ You may obtain a copy of the License at
931
+
932
+ http://www.apache.org/licenses/LICENSE-2.0
933
+
934
+ Unless required by applicable law or agreed to in writing, software
935
+ distributed under the License is distributed on an "AS IS" BASIS,
936
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
937
+ See the License for the specific language governing permissions and
938
+ limitations under the License.
939
+ */
1884
940
 
1885
941
  /**
1886
- * Format either small or big number
1887
942
  *
1888
- * @private within the library
1889
943
  */
1890
- function formatNumber(value) {
1891
- if (value === 0) {
1892
- return '0';
1893
- }
1894
- for (var exponent = 0; exponent < 15; exponent++) {
1895
- var factor = Math.pow(10, exponent);
1896
- var valueRounded = Math.round(value * factor) / factor;
1897
- if (Math.abs(value - valueRounded) / value <
1898
- 0.001 /* <- TODO: Pass as option, pass to executionReportJsonToString as option */) {
1899
- return valueRounded.toFixed(exponent);
1900
- }
1901
- }
1902
- return value.toString();
944
+ function removeDiacritics(input) {
945
+ /*eslint no-control-regex: "off"*/
946
+ return input.replace(/[^\u0000-\u007E]/g, function (a) {
947
+ return DIACRITIC_VARIANTS_LETTERS[a] || a;
948
+ });
1903
949
  }
1904
950
 
1905
951
  /**
1906
- * Returns the same value that is passed as argument.
1907
- * No side effects.
1908
- *
1909
- * Note: It can be usefull for leveling indentation
1910
- *
1911
- * @param value any values
1912
- * @returns the same values
952
+ * Counts number of words in the text
1913
953
  */
1914
- function just(value) {
1915
- if (value === undefined) {
1916
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
1917
- return undefined;
1918
- }
1919
- return value;
954
+ function countWords(text) {
955
+ text = text.replace(/[\p{Extended_Pictographic}]/gu, 'a');
956
+ text = removeDiacritics(text);
957
+ return text.split(/[^a-zа-я0-9]+/i).filter(function (word) { return word.length > 0; }).length;
1920
958
  }
1921
959
 
1922
960
  /**
1923
- * Create a markdown table from a 2D array of strings
1924
- *
1925
- * @private within the library
961
+ * Index of all counter functions
1926
962
  */
1927
- function createMarkdownTable(table) {
1928
- var columnWidths = table.reduce(function (widths, row) {
1929
- row.forEach(function (cell, columnIndex) {
1930
- var cellLength = cell.length;
1931
- if (!widths[columnIndex] || cellLength > widths[columnIndex]) {
1932
- widths[columnIndex] = cellLength;
1933
- }
1934
- });
1935
- return widths;
1936
- }, []);
1937
- var header = "| ".concat(table[0]
1938
- .map(function (cell, columnIndex) { return cell.padEnd(columnWidths[columnIndex]); })
1939
- .join(' | '), " |");
1940
- var separator = "|".concat(columnWidths.map(function (width) { return '-'.repeat(width + 2); }).join('|'), "|");
1941
- var rows = table.slice(1).map(function (row) {
1942
- var paddedRow = row.map(function (cell, columnIndex) {
1943
- return cell.padEnd(columnWidths[columnIndex]);
1944
- });
1945
- return "| ".concat(paddedRow.join(' | '), " |");
1946
- });
1947
- return __spreadArray([header, separator], __read(rows), false).join('\n');
1948
- }
963
+ var CountUtils = {
964
+ CHARACTERS: countCharacters,
965
+ WORDS: countWords,
966
+ SENTENCES: countSentences,
967
+ PARAGRAPHS: countParagraphs,
968
+ LINES: countLines,
969
+ PAGES: countPages,
970
+ };
1949
971
 
1950
972
  /**
1951
- * Function createMarkdownChart will draw a chart in markdown from ⬛+🟦 tiles
1952
- *
1953
- * @private within the library
973
+ * Function isValidJsonString will tell you if the string is valid JSON or not
1954
974
  */
1955
- function createMarkdownChart(options) {
1956
- var e_1, _a;
1957
- var nameHeader = options.nameHeader, valueHeader = options.valueHeader, items = options.items, width = options.width, unitName = options.unitName;
1958
- var from = Math.min.apply(Math, __spreadArray([], __read(items.map(function (item) { return item.from; })), false));
1959
- var to = Math.max.apply(Math, __spreadArray([], __read(items.map(function (item) { return item.to; })), false));
1960
- var scale = width / (to - from);
1961
- var table = [[nameHeader, valueHeader]];
975
+ function isValidJsonString(value) {
1962
976
  try {
1963
- for (var items_1 = __values(items), items_1_1 = items_1.next(); !items_1_1.done; items_1_1 = items_1.next()) {
1964
- var item = items_1_1.value;
1965
- var before = Math.round((item.from - from) * scale);
1966
- var during = Math.round((item.to - item.from) * scale);
1967
- var after = width - before - during;
1968
- table.push([removeEmojis(item.title).trim(), '░'.repeat(before) + '█'.repeat(during) + '░'.repeat(after)]);
1969
- }
977
+ JSON.parse(value);
978
+ return true;
1970
979
  }
1971
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
1972
- finally {
1973
- try {
1974
- if (items_1_1 && !items_1_1.done && (_a = items_1.return)) _a.call(items_1);
980
+ catch (error) {
981
+ if (!(error instanceof Error)) {
982
+ throw error;
1975
983
  }
1976
- finally { if (e_1) throw e_1.error; }
984
+ if (error.message.includes('Unexpected token')) {
985
+ return false;
986
+ }
987
+ return false;
1977
988
  }
1978
- var legend = "_Note: Each \u2588 represents ".concat(formatNumber(1 / scale), " ").concat(unitName, ", width of ").concat(valueHeader.toLowerCase(), " is ").concat(formatNumber(to - from), " ").concat(unitName, " = ").concat(width, " squares_");
1979
- return createMarkdownTable(table) + '\n\n' + legend;
1980
989
  }
1981
- /**
1982
- * TODO: Maybe use Mermain Gant Diagrams
1983
- * @see https://jojozhuang.github.io/tutorial/mermaid-cheat-sheet/
1984
- */
1985
990
 
1986
991
  /**
1987
- * Function escapeMarkdownBlock will escape markdown block if needed
1988
- * It is useful when you want have block in block
992
+ * Makes first letter of a string uppercase
993
+ *
1989
994
  */
1990
- function escapeMarkdownBlock(value) {
1991
- return value.replace(/```/g, '\\`\\`\\`');
995
+ function capitalize(word) {
996
+ return word.substring(0, 1).toUpperCase() + word.substring(1);
1992
997
  }
1993
998
 
1994
999
  /**
1995
- * Default options for generating an execution report string
1996
- */
1997
- var ExecutionReportStringOptionsDefaults = {
1998
- taxRate: 0,
1999
- chartsWidth: 36,
2000
- };
2001
-
2002
- /**
2003
- * The thresholds for the relative time in the `moment` library.
1000
+ * Extracts all code blocks from markdown.
2004
1001
  *
2005
- * @see https://momentjscom.readthedocs.io/en/latest/moment/07-customization/13-relative-time-threshold/
2006
- */
2007
- var MOMENT_ARG_THRESHOLDS = {
2008
- ss: 3, // <- least number of seconds to be counted in seconds, minus 1. Must be set after setting the `s` unit or without setting the `s` unit.
2009
- };
2010
-
2011
- /**
2012
- * Count the duration of working time
1002
+ * Note: There are 3 simmilar function:
1003
+ * - `extractBlock` just extracts the content of the code block which is also used as build-in function for postprocessing
1004
+ * - `extractOneBlockFromMarkdown` extracts exactly one code block with language of the code block
1005
+ * - `extractAllBlocksFromMarkdown` extracts all code blocks with language of the code block
1006
+ *
1007
+ * @param markdown any valid markdown
1008
+ * @returns code blocks with language and content
2013
1009
  *
2014
- * @private within the library
2015
1010
  */
2016
- function countWorkingDuration(items) {
1011
+ function extractAllBlocksFromMarkdown(markdown) {
2017
1012
  var e_1, _a;
2018
- var steps = Array.from(new Set(items.flatMap(function (item) { return [item.from, item.to]; })));
2019
- steps.sort(function (a, b) { return a - b; });
2020
- var intervals = steps.map(function (step, index) { return [step, steps[index + 1] || 0]; }).slice(0, -1);
2021
- var duration = 0;
2022
- var _loop_1 = function (interval) {
2023
- var _b = __read(interval, 2), from = _b[0], to = _b[1];
2024
- if (items.some(function (item) { return item.from < to && item.to > from; })) {
2025
- duration += to - from;
2026
- }
2027
- };
1013
+ var codeBlocks = [];
1014
+ var lines = markdown.split('\n');
1015
+ var currentCodeBlock = null;
2028
1016
  try {
2029
- for (var intervals_1 = __values(intervals), intervals_1_1 = intervals_1.next(); !intervals_1_1.done; intervals_1_1 = intervals_1.next()) {
2030
- var interval = intervals_1_1.value;
2031
- _loop_1(interval);
1017
+ for (var lines_1 = __values(lines), lines_1_1 = lines_1.next(); !lines_1_1.done; lines_1_1 = lines_1.next()) {
1018
+ var line = lines_1_1.value;
1019
+ if (line.startsWith('```')) {
1020
+ var language = line.slice(3).trim() || null;
1021
+ if (currentCodeBlock === null) {
1022
+ currentCodeBlock = { language: language, content: '' };
1023
+ }
1024
+ else {
1025
+ if (language !== null) {
1026
+ // [🌻]
1027
+ throw new Error("".concat(capitalize(currentCodeBlock.language || 'the'), " code block was not closed and already opening new ").concat(language, " code block"));
1028
+ }
1029
+ codeBlocks.push(currentCodeBlock);
1030
+ currentCodeBlock = null;
1031
+ }
1032
+ }
1033
+ else if (currentCodeBlock !== null) {
1034
+ if (currentCodeBlock.content !== '') {
1035
+ currentCodeBlock.content += '\n';
1036
+ }
1037
+ currentCodeBlock.content += line.split('\\`\\`\\`').join('```') /* <- TODO: Maybe make propper unescape */;
1038
+ }
2032
1039
  }
2033
1040
  }
2034
1041
  catch (e_1_1) { e_1 = { error: e_1_1 }; }
2035
1042
  finally {
2036
1043
  try {
2037
- if (intervals_1_1 && !intervals_1_1.done && (_a = intervals_1.return)) _a.call(intervals_1);
1044
+ if (lines_1_1 && !lines_1_1.done && (_a = lines_1.return)) _a.call(lines_1);
2038
1045
  }
2039
1046
  finally { if (e_1) throw e_1.error; }
2040
1047
  }
2041
- return duration;
1048
+ if (currentCodeBlock !== null) {
1049
+ // [🌻]
1050
+ throw new Error("".concat(capitalize(currentCodeBlock.language || 'the'), " code block was not closed at the end of the markdown"));
1051
+ }
1052
+ return codeBlocks;
2042
1053
  }
2043
1054
 
2044
1055
  /**
2045
- * Converts execution report from JSON to string format
1056
+ * Utility function to extract all list items from markdown
1057
+ *
1058
+ * Note: It works with both ul and ol
1059
+ * Note: It omits list items in code blocks
1060
+ * Note: It flattens nested lists
1061
+ * Note: It can not work with html syntax and comments
1062
+ *
1063
+ * @param markdown any valid markdown
1064
+ * @returns
2046
1065
  */
2047
- function executionReportJsonToString(executionReportJson, options) {
1066
+ function extractAllListItemsFromMarkdown(markdown) {
2048
1067
  var e_1, _a;
2049
- var _b, _c, _d, _e, _f, _g;
2050
- var _h = __assign(__assign({}, ExecutionReportStringOptionsDefaults), (options || {})), taxRate = _h.taxRate, chartsWidth = _h.chartsWidth;
2051
- var executionReportString = spaceTrim(function (block) { return "\n # ".concat(executionReportJson.title || 'Execution report', "\n\n ").concat(block(executionReportJson.description || ''), "\n "); });
2052
- var headerList = [];
2053
- if (executionReportJson.promptbookUrl) {
2054
- headerList.push("PROMPTBOOK URL ".concat(executionReportJson.promptbookUrl));
2055
- }
2056
- headerList.push("PROMPTBOOK VERSION ".concat(executionReportJson.promptbookUsedVersion) +
2057
- (!executionReportJson.promptbookRequestedVersion
2058
- ? ''
2059
- : " *(requested ".concat(executionReportJson.promptbookRequestedVersion, ")*")));
2060
- if (executionReportJson.promptExecutions.length !== 0) {
2061
- // TODO: What if startedAt OR/AND completedAt is not defined?
2062
- var startedAt = moment(Math.min.apply(Math, __spreadArray([], __read(executionReportJson.promptExecutions
2063
- .filter(function (promptExecution) { var _a, _b; return (_b = (_a = promptExecution.result) === null || _a === void 0 ? void 0 : _a.timing) === null || _b === void 0 ? void 0 : _b.start; })
2064
- .map(function (promptExecution) { return moment(promptExecution.result.timing.start).valueOf(); })), false)));
2065
- var completedAt = moment(Math.max.apply(Math, __spreadArray([], __read(executionReportJson.promptExecutions
2066
- .filter(function (promptExecution) { var _a, _b; return (_b = (_a = promptExecution.result) === null || _a === void 0 ? void 0 : _a.timing) === null || _b === void 0 ? void 0 : _b.complete; })
2067
- .map(function (promptExecution) { return moment(promptExecution.result.timing.complete).valueOf(); })), false)));
2068
- var timingItems = executionReportJson.promptExecutions.map(function (promptExecution) {
2069
- var _a, _b, _c, _d;
2070
- return ({
2071
- title: promptExecution.prompt.title,
2072
- from: moment((_b = (_a = promptExecution.result) === null || _a === void 0 ? void 0 : _a.timing) === null || _b === void 0 ? void 0 : _b.start).valueOf() / 1000,
2073
- to: moment((_d = (_c = promptExecution.result) === null || _c === void 0 ? void 0 : _c.timing) === null || _d === void 0 ? void 0 : _d.complete).valueOf() / 1000,
2074
- });
2075
- });
2076
- var costItems = executionReportJson.promptExecutions
2077
- .filter(function (promptExecution) { var _a, _b; return typeof ((_b = (_a = promptExecution.result) === null || _a === void 0 ? void 0 : _a.usage) === null || _b === void 0 ? void 0 : _b.price) === 'number'; })
2078
- .map(function (promptExecution) {
2079
- var _a, _b;
2080
- return ({
2081
- title: promptExecution.prompt.title,
2082
- from: 0,
2083
- to: ((_b = (_a = promptExecution.result) === null || _a === void 0 ? void 0 : _a.usage) === null || _b === void 0 ? void 0 : _b.price) * (1 + taxRate),
2084
- });
2085
- });
2086
- var duration = moment.duration(completedAt.diff(startedAt));
2087
- var llmDuration = moment.duration(countWorkingDuration(timingItems) * 1000);
2088
- var executionsWithKnownCost = executionReportJson.promptExecutions.filter(function (promptExecution) { var _a, _b; return (((_b = (_a = promptExecution.result) === null || _a === void 0 ? void 0 : _a.usage) === null || _b === void 0 ? void 0 : _b.price) || 'UNKNOWN') !== 'UNKNOWN'; });
2089
- var cost = executionsWithKnownCost.reduce(function (cost, promptExecution) { return cost + (promptExecution.result.usage.price || 0); }, 0);
2090
- headerList.push("STARTED AT ".concat(moment(startedAt).format("YYYY-MM-DD HH:mm:ss")));
2091
- headerList.push("COMPLETED AT ".concat(moment(completedAt).format("YYYY-MM-DD HH:mm:ss")));
2092
- headerList.push("TOTAL DURATION ".concat(duration.humanize(MOMENT_ARG_THRESHOLDS)));
2093
- headerList.push("TOTAL LLM DURATION ".concat(llmDuration.humanize(MOMENT_ARG_THRESHOLDS)));
2094
- headerList.push("TOTAL COST $".concat(formatNumber(cost * (1 + taxRate))) +
2095
- (executionsWithKnownCost.length === executionReportJson.promptExecutions.length
2096
- ? ''
2097
- : " *(Some cost is unknown)*") +
2098
- (taxRate !== 0 ? " *(with tax ".concat(taxRate * 100, "%)*") : ''));
2099
- executionReportString += '\n\n' + headerList.map(function (header) { return "- ".concat(header); }).join('\n');
2100
- executionReportString +=
2101
- '\n\n' +
2102
- '## 🗃 Index' +
2103
- '\n\n' +
2104
- executionReportJson.promptExecutions
2105
- .map(function (promptExecution) {
2106
- // TODO: Make some better system to convert hedings to links
2107
- var hash = normalizeToKebabCase(promptExecution.prompt.title);
2108
- if (/^\s*\p{Extended_Pictographic}/u.test(promptExecution.prompt.title)) {
2109
- hash = '-' + hash;
2110
- }
2111
- // TODO: Make working hash link for the template in md + pdf
2112
- return "- [".concat(promptExecution.prompt.title, "](#").concat(hash, ")");
2113
- })
2114
- .join('\n');
2115
- executionReportString +=
2116
- '\n\n' +
2117
- '## ⌚ Time chart' +
2118
- '\n\n' +
2119
- createMarkdownChart({
2120
- nameHeader: 'Template',
2121
- valueHeader: 'Timeline',
2122
- items: timingItems,
2123
- width: chartsWidth,
2124
- unitName: 'seconds',
2125
- });
2126
- executionReportString +=
2127
- '\n\n' +
2128
- '## 💸 Cost chart' +
2129
- '\n\n' +
2130
- createMarkdownChart({
2131
- nameHeader: 'Template',
2132
- valueHeader: 'Cost',
2133
- items: costItems,
2134
- width: chartsWidth,
2135
- unitName: 'USD',
2136
- });
2137
- }
2138
- else {
2139
- headerList.push("TOTAL COST $0 *(Nothing executed)*");
2140
- }
2141
- var _loop_1 = function (promptExecution) {
2142
- executionReportString += '\n\n\n\n' + "## ".concat(promptExecution.prompt.title);
2143
- var templateList = [];
2144
- // TODO: What if startedAt OR/AND completedAt is not defined?
2145
- var startedAt = moment((_c = (_b = promptExecution.result) === null || _b === void 0 ? void 0 : _b.timing) === null || _c === void 0 ? void 0 : _c.start);
2146
- var completedAt = moment((_e = (_d = promptExecution.result) === null || _d === void 0 ? void 0 : _d.timing) === null || _e === void 0 ? void 0 : _e.complete);
2147
- var duration = moment.duration(completedAt.diff(startedAt));
2148
- // Not need here:
2149
- // > templateList.push(`STARTED AT ${moment(startedAt).calendar()}`);
2150
- templateList.push("DURATION ".concat(duration.humanize(MOMENT_ARG_THRESHOLDS)));
2151
- if (typeof ((_g = (_f = promptExecution.result) === null || _f === void 0 ? void 0 : _f.usage) === null || _g === void 0 ? void 0 : _g.price) === 'number') {
2152
- templateList.push("COST $".concat(formatNumber(promptExecution.result.usage.price * (1 + taxRate))) +
2153
- (taxRate !== 0 ? " *(with tax ".concat(taxRate * 100, "%)*") : ''));
2154
- }
2155
- else {
2156
- templateList.push("COST UNKNOWN");
2157
- }
2158
- executionReportString += '\n\n' + templateList.map(function (header) { return "- ".concat(header); }).join('\n');
2159
- /*
2160
- - MODEL VARIANT ${promptExecution.prompt.modelRequirements.modelVariant}
2161
- - MODEL NAME \`${promptExecution.result?.model}\` (requested \`${
2162
- promptExecution.prompt.modelRequirements.modelName
2163
-
2164
- */
2165
- if (just(true)) {
2166
- executionReportString +=
2167
- '\n\n\n\n' +
2168
- spaceTrim(function (block) { return "\n\n ### Prompt\n\n ```\n ".concat(block(escapeMarkdownBlock(promptExecution.prompt.content)), "\n ```\n\n "); });
2169
- }
2170
- if (promptExecution.result && promptExecution.result.content) {
2171
- executionReportString +=
2172
- '\n\n\n\n' +
2173
- spaceTrim(function (block) { return "\n\n ### Result\n\n ```\n ".concat(block(escapeMarkdownBlock(promptExecution.result.content)), "\n ```\n "); });
2174
- }
2175
- if (promptExecution.error && promptExecution.error.message) {
2176
- executionReportString +=
2177
- '\n\n\n\n' +
2178
- spaceTrim(function (block) { return "\n\n ### Error\n\n ```\n ".concat(block(escapeMarkdownBlock(promptExecution.error.message)), "\n ```\n\n "); });
2179
- }
2180
- };
1068
+ var lines = markdown.split('\n');
1069
+ var listItems = [];
1070
+ var isInCodeBlock = false;
2181
1071
  try {
2182
- for (var _j = __values(executionReportJson.promptExecutions), _k = _j.next(); !_k.done; _k = _j.next()) {
2183
- var promptExecution = _k.value;
2184
- _loop_1(promptExecution);
1072
+ for (var lines_1 = __values(lines), lines_1_1 = lines_1.next(); !lines_1_1.done; lines_1_1 = lines_1.next()) {
1073
+ var line = lines_1_1.value;
1074
+ var trimmedLine = line.trim();
1075
+ if (trimmedLine.startsWith('```')) {
1076
+ isInCodeBlock = !isInCodeBlock;
1077
+ }
1078
+ if (!isInCodeBlock && (trimmedLine.startsWith('-') || trimmedLine.match(/^\d+\./))) {
1079
+ var listItem = trimmedLine.replace(/^-|\d+\./, '').trim();
1080
+ listItems.push(listItem);
1081
+ }
2185
1082
  }
2186
1083
  }
2187
1084
  catch (e_1_1) { e_1 = { error: e_1_1 }; }
2188
1085
  finally {
2189
1086
  try {
2190
- if (_k && !_k.done && (_a = _j.return)) _a.call(_j);
1087
+ if (lines_1_1 && !lines_1_1.done && (_a = lines_1.return)) _a.call(lines_1);
2191
1088
  }
2192
1089
  finally { if (e_1) throw e_1.error; }
2193
1090
  }
2194
- executionReportString = prettifyMarkdown(executionReportString);
2195
- return executionReportString;
1091
+ return listItems;
2196
1092
  }
1093
+
2197
1094
  /**
2198
- * TODO: Add mermaid chart for every report
2199
- * TODO: [🧠] Allow to filter out some parts of the report by options
1095
+ * Extracts exactly ONE code block from markdown.
1096
+ *
1097
+ * Note: If there are multiple or no code blocks the function throws an error
1098
+ *
1099
+ * Note: There are 3 simmilar function:
1100
+ * - `extractBlock` just extracts the content of the code block which is also used as build-in function for postprocessing
1101
+ * - `extractOneBlockFromMarkdown` extracts exactly one code block with language of the code block
1102
+ * - `extractAllBlocksFromMarkdown` extracts all code blocks with language of the code block
1103
+ *
1104
+ * @param markdown any valid markdown
1105
+ * @returns code block with language and content
1106
+ */
1107
+ function extractOneBlockFromMarkdown(markdown) {
1108
+ var codeBlocks = extractAllBlocksFromMarkdown(markdown);
1109
+ if (codeBlocks.length !== 1) {
1110
+ // TODO: Report more specific place where the error happened
1111
+ throw new Error(/* <- [🌻] */ 'There should be exactly one code block in the markdown');
1112
+ }
1113
+ return codeBlocks[0];
1114
+ }
1115
+ /***
1116
+ * TODO: [🍓][🌻] !!! Decide of this is internal util, external util OR validator/postprocessor
2200
1117
  */
2201
1118
 
2202
1119
  /**
2203
- * Function isValidJsonString will tell you if the string is valid JSON or not
1120
+ * Removes HTML or Markdown comments from a string.
1121
+ *
1122
+ * @param {string} content - The string to remove comments from.
1123
+ * @returns {string} The input string with all comments removed.
2204
1124
  */
2205
- function isValidJsonString(value) {
2206
- try {
2207
- JSON.parse(value);
2208
- return true;
2209
- }
2210
- catch (error) {
2211
- if (!(error instanceof Error)) {
2212
- throw error;
2213
- }
2214
- if (error.message.includes('Unexpected token')) {
2215
- return false;
2216
- }
2217
- return false;
2218
- }
1125
+ function removeContentComments(content) {
1126
+ return spaceTrim(content.replace(/<!--(.*?)-->/gs, ''));
1127
+ }
1128
+
1129
+ /**
1130
+ * Removes Markdown formatting tags from a string.
1131
+ *
1132
+ * @param {string} str - The string to remove Markdown tags from.
1133
+ * @returns {string} The input string with all Markdown tags removed.
1134
+ */
1135
+ function removeMarkdownFormatting(str) {
1136
+ // Remove bold formatting
1137
+ str = str.replace(/\*\*(.*?)\*\*/g, '$1');
1138
+ // Remove italic formatting
1139
+ str = str.replace(/\*(.*?)\*/g, '$1');
1140
+ // Remove code formatting
1141
+ str = str.replace(/`(.*?)`/g, '$1');
1142
+ return str;
2219
1143
  }
2220
1144
 
2221
1145
  /**
@@ -2627,6 +1551,44 @@ function intersection() {
2627
1551
  return intersection;
2628
1552
  }
2629
1553
 
1554
+ /**
1555
+ * Creates a new set with all elements that are present in either set
1556
+ */
1557
+ function union() {
1558
+ var e_1, _a, e_2, _b;
1559
+ var sets = [];
1560
+ for (var _i = 0; _i < arguments.length; _i++) {
1561
+ sets[_i] = arguments[_i];
1562
+ }
1563
+ var union = new Set();
1564
+ try {
1565
+ for (var sets_1 = __values(sets), sets_1_1 = sets_1.next(); !sets_1_1.done; sets_1_1 = sets_1.next()) {
1566
+ var set = sets_1_1.value;
1567
+ try {
1568
+ for (var _c = (e_2 = void 0, __values(Array.from(set))), _d = _c.next(); !_d.done; _d = _c.next()) {
1569
+ var item = _d.value;
1570
+ union.add(item);
1571
+ }
1572
+ }
1573
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
1574
+ finally {
1575
+ try {
1576
+ if (_d && !_d.done && (_b = _c.return)) _b.call(_c);
1577
+ }
1578
+ finally { if (e_2) throw e_2.error; }
1579
+ }
1580
+ }
1581
+ }
1582
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
1583
+ finally {
1584
+ try {
1585
+ if (sets_1_1 && !sets_1_1.done && (_a = sets_1.return)) _a.call(sets_1);
1586
+ }
1587
+ finally { if (e_1) throw e_1.error; }
1588
+ }
1589
+ return union;
1590
+ }
1591
+
2630
1592
  /**
2631
1593
  * Function trimCodeBlock will trim starting and ending code block from the string if it is present.
2632
1594
  *
@@ -2744,5 +1706,5 @@ var normalizeTo = {
2744
1706
  * Note: [🕙] It does not make sence to have simple lower / UPPER case normalization
2745
1707
  */
2746
1708
 
2747
- export { CountUtils, DIACRITIC_VARIANTS_LETTERS, ExecutionReportStringOptionsDefaults, assertsExecutionSuccessful, capitalize, checkExpectations, countCharacters, countLines, countPages, countParagraphs, countSentences, countWords, decapitalize, difference, executionReportJsonToString, extractAllBlocksFromMarkdown, extractAllListItemsFromMarkdown, extractBlock, extractOneBlockFromMarkdown, extractParameters, extractParametersFromPromptTemplate, extractVariables, intersection, isPassingExpectations, isValidJsonString, isValidKeyword, nameToUriPart, nameToUriParts, normalizeTo, normalizeToKebabCase, normalizeTo_PascalCase, normalizeTo_SCREAMING_CASE, normalizeTo_camelCase, normalizeTo_snake_case, normalizeWhitespaces, parseKeywords, parseKeywordsFromString, parseNumber, prettifyPromptbookString, removeContentComments, removeDiacritics, removeEmojis, removeMarkdownFormatting, removeQuotes, renameParameter, renderPromptbookMermaid, replaceParameters, searchKeywords, splitIntoSentences, titleToName, trimCodeBlock, trimEndOfCodeBlock, union, unwrapResult };
1709
+ export { CountUtils, DIACRITIC_VARIANTS_LETTERS, capitalize, countCharacters, countLines, countPages, countParagraphs, countSentences, countWords, decapitalize, difference, extractAllBlocksFromMarkdown, extractAllListItemsFromMarkdown, extractBlock, extractOneBlockFromMarkdown, extractParameters, extractParametersFromPromptTemplate, extractVariables, forEachAsync, intersection, isValidJsonString, isValidKeyword, nameToUriPart, nameToUriParts, normalizeTo, normalizeToKebabCase, normalizeTo_PascalCase, normalizeTo_SCREAMING_CASE, normalizeTo_camelCase, normalizeTo_snake_case, normalizeWhitespaces, parseKeywords, parseKeywordsFromString, parseNumber, removeContentComments, removeDiacritics, removeEmojis, removeMarkdownFormatting, removeQuotes, renameParameter, renderPromptbookMermaid, replaceParameters, searchKeywords, splitIntoSentences, titleToName, trimCodeBlock, trimEndOfCodeBlock, union, unwrapResult };
2748
1710
  //# sourceMappingURL=index.es.js.map