@promptbook/editable 0.82.0 → 0.84.0-0

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 +4 -0
  2. package/esm/index.es.js +3890 -320
  3. package/esm/index.es.js.map +1 -1
  4. package/esm/typings/src/_packages/editable.index.d.ts +82 -2
  5. package/esm/typings/src/_packages/types.index.d.ts +26 -0
  6. package/esm/typings/src/commands/BOOK_VERSION/BookVersionCommand.d.ts +1 -1
  7. package/esm/typings/src/commands/BOOK_VERSION/bookVersionCommandParser.d.ts +1 -1
  8. package/esm/typings/src/commands/EXPECT/expectCommandParser.d.ts +1 -1
  9. package/esm/typings/src/commands/FOREACH/ForeachCommand.d.ts +1 -1
  10. package/esm/typings/src/commands/FOREACH/foreachCommandParser.d.ts +1 -1
  11. package/esm/typings/src/commands/FORMAT/formatCommandParser.d.ts +1 -1
  12. package/esm/typings/src/commands/FORMFACTOR/FormfactorCommand.d.ts +1 -1
  13. package/esm/typings/src/commands/FORMFACTOR/formfactorCommandParser.d.ts +1 -1
  14. package/esm/typings/src/commands/JOKER/JokerCommand.d.ts +1 -1
  15. package/esm/typings/src/commands/JOKER/jokerCommandParser.d.ts +1 -1
  16. package/esm/typings/src/commands/KNOWLEDGE/KnowledgeCommand.d.ts +2 -2
  17. package/esm/typings/src/commands/KNOWLEDGE/knowledgeCommandParser.d.ts +1 -1
  18. package/esm/typings/src/commands/KNOWLEDGE/utils/{sourceContentToName.d.ts → knowledgeSourceContentToName.d.ts} +2 -2
  19. package/esm/typings/src/commands/MODEL/ModelCommand.d.ts +2 -1
  20. package/esm/typings/src/commands/MODEL/modelCommandParser.d.ts +2 -1
  21. package/esm/typings/src/commands/PARAMETER/ParameterCommand.d.ts +1 -1
  22. package/esm/typings/src/commands/PARAMETER/parameterCommandParser.d.ts +1 -1
  23. package/esm/typings/src/commands/PERSONA/PersonaCommand.d.ts +1 -1
  24. package/esm/typings/src/commands/PERSONA/personaCommandParser.d.ts +1 -1
  25. package/esm/typings/src/commands/POSTPROCESS/PostprocessCommand.d.ts +1 -1
  26. package/esm/typings/src/commands/POSTPROCESS/postprocessCommandParser.d.ts +1 -1
  27. package/esm/typings/src/commands/SECTION/SectionCommand.d.ts +1 -1
  28. package/esm/typings/src/commands/SECTION/sectionCommandParser.d.ts +1 -1
  29. package/esm/typings/src/commands/URL/UrlCommand.d.ts +1 -1
  30. package/esm/typings/src/commands/URL/urlCommandParser.d.ts +1 -1
  31. package/esm/typings/src/commands/X_ACTION/ActionCommand.d.ts +1 -1
  32. package/esm/typings/src/commands/X_ACTION/actionCommandParser.d.ts +1 -1
  33. package/esm/typings/src/commands/X_INSTRUMENT/InstrumentCommand.d.ts +1 -1
  34. package/esm/typings/src/commands/X_INSTRUMENT/instrumentCommandParser.d.ts +1 -1
  35. package/esm/typings/src/commands/_common/getParserForCommand.d.ts +1 -1
  36. package/esm/typings/src/commands/_common/parseCommand.d.ts +1 -1
  37. package/esm/typings/src/commands/_common/stringifyCommand.d.ts +1 -0
  38. package/esm/typings/src/commands/_common/types/CommandParser.d.ts +8 -0
  39. package/esm/typings/src/commands/_common/types/CommandUsagePlaces.d.ts +2 -0
  40. package/esm/typings/src/commands/index.d.ts +1 -1
  41. package/esm/typings/src/pipeline/PipelineJson/KnowledgeSourceJson.d.ts +1 -1
  42. package/esm/typings/src/utils/editable/edit-pipeline-string/addPipelineCommand.d.ts +17 -0
  43. package/esm/typings/src/utils/editable/edit-pipeline-string/deflatePipeline.d.ts +10 -0
  44. package/esm/typings/src/utils/editable/{utils → edit-pipeline-string}/removePipelineCommand.d.ts +1 -1
  45. package/esm/typings/src/utils/editable/edit-pipeline-string/removePipelineCommand.test.d.ts +1 -0
  46. package/esm/typings/src/utils/editable/utils/isFlatPipeline.d.ts +7 -0
  47. package/esm/typings/src/utils/editable/utils/renamePipelineParameter.d.ts +3 -0
  48. package/package.json +4 -2
  49. package/umd/index.umd.js +3913 -323
  50. package/umd/index.umd.js.map +1 -1
  51. /package/esm/typings/src/commands/KNOWLEDGE/utils/{sourceContentToName.test.d.ts → knowledgeSourceContentToName.test.d.ts} +0 -0
  52. /package/esm/typings/src/utils/editable/{utils/removePipelineCommand.test.d.ts → edit-pipeline-string/addPipelineCommand.test.d.ts} +0 -0
package/umd/index.umd.js CHANGED
@@ -1,12 +1,13 @@
1
1
  (function (global, factory) {
2
- typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('spacetrim')) :
3
- typeof define === 'function' && define.amd ? define(['exports', 'spacetrim'], factory) :
4
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global["promptbook-editable"] = {}, global.spaceTrim));
5
- })(this, (function (exports, spaceTrim) { 'use strict';
2
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('spacetrim'), require('papaparse'), require('crypto-js'), require('crypto-js/enc-hex')) :
3
+ typeof define === 'function' && define.amd ? define(['exports', 'spacetrim', 'papaparse', 'crypto-js', 'crypto-js/enc-hex'], factory) :
4
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global["promptbook-editable"] = {}, global.spaceTrim, global.papaparse, global.cryptoJs, global.hexEncoder));
5
+ })(this, (function (exports, spaceTrim, papaparse, cryptoJs, hexEncoder) { 'use strict';
6
6
 
7
7
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
8
8
 
9
9
  var spaceTrim__default = /*#__PURE__*/_interopDefaultLegacy(spaceTrim);
10
+ var hexEncoder__default = /*#__PURE__*/_interopDefaultLegacy(hexEncoder);
10
11
 
11
12
  // ⚠️ WARNING: This code has been generated so that any manual changes will be overwritten
12
13
  /**
@@ -22,7 +23,7 @@
22
23
  * @generated
23
24
  * @see https://github.com/webgptorg/promptbook
24
25
  */
25
- var PROMPTBOOK_ENGINE_VERSION = '0.82.0-3';
26
+ var PROMPTBOOK_ENGINE_VERSION = '0.83.0';
26
27
  /**
27
28
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
28
29
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -70,6 +71,44 @@
70
71
  return __assign.apply(this, arguments);
71
72
  };
72
73
 
74
+ function __awaiter(thisArg, _arguments, P, generator) {
75
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
76
+ return new (P || (P = Promise))(function (resolve, reject) {
77
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
78
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
79
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
80
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
81
+ });
82
+ }
83
+
84
+ function __generator(thisArg, body) {
85
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
86
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
87
+ function verb(n) { return function (v) { return step([n, v]); }; }
88
+ function step(op) {
89
+ if (f) throw new TypeError("Generator is already executing.");
90
+ while (_) try {
91
+ 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;
92
+ if (y = 0, t) op = [op[0] & 2, t.value];
93
+ switch (op[0]) {
94
+ case 0: case 1: t = op; break;
95
+ case 4: _.label++; return { value: op[1], done: false };
96
+ case 5: _.label++; y = op[1]; op = [0]; continue;
97
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
98
+ default:
99
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
100
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
101
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
102
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
103
+ if (t[2]) _.ops.pop();
104
+ _.trys.pop(); continue;
105
+ }
106
+ op = body.call(thisArg, _);
107
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
108
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
109
+ }
110
+ }
111
+
73
112
  function __values(o) {
74
113
  var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
75
114
  if (m) return m.call(o);
@@ -110,128 +149,23 @@
110
149
  }
111
150
 
112
151
  /**
113
- * Function `removePipelineCommand` will remove one command from pipeline string
152
+ * Returns the same value that is passed as argument.
153
+ * No side effects.
114
154
  *
115
- * @public exported from `@promptbook/editable`
116
- */
117
- function removePipelineCommand(options) {
118
- var e_1, _a;
119
- var command = options.command, pipeline = options.pipeline;
120
- var lines = pipeline.split('\n');
121
- // TODO: [🧽] DRY
122
- var currentType = 'MARKDOWN';
123
- var newLines = [];
124
- try {
125
- for (var lines_1 = __values(lines), lines_1_1 = lines_1.next(); !lines_1_1.done; lines_1_1 = lines_1.next()) {
126
- var line = lines_1_1.value;
127
- if (currentType === 'MARKDOWN') {
128
- if (line.startsWith('```')) {
129
- currentType = 'CODE_BLOCK';
130
- }
131
- else if (line.includes('<!--')) {
132
- currentType = 'COMMENT';
133
- }
134
- }
135
- else if (currentType === 'CODE_BLOCK') {
136
- if (line.startsWith('```')) {
137
- currentType = 'MARKDOWN';
138
- }
139
- }
140
- else if (currentType === 'COMMENT') {
141
- if (line.includes('-->')) {
142
- currentType = 'MARKDOWN';
143
- }
144
- }
145
- if (currentType === 'MARKDOWN' && /^(-|\d\))/m.test(line) && line.toUpperCase().includes(command)) {
146
- continue;
147
- }
148
- newLines.push(line);
149
- }
150
- }
151
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
152
- finally {
153
- try {
154
- if (lines_1_1 && !lines_1_1.done && (_a = lines_1.return)) _a.call(lines_1);
155
- }
156
- finally { if (e_1) throw e_1.error; }
157
- }
158
- var newPipeline = spaceTrim__default["default"](newLines.join('\n'));
159
- return newPipeline;
160
- }
161
-
162
- /**
163
- * This error indicates that the promptbook object has valid syntax (=can be parsed) but contains logical errors (like circular dependencies)
155
+ * Note: It can be usefull for:
164
156
  *
165
- * @public exported from `@promptbook/core`
166
- */
167
- var PipelineLogicError = /** @class */ (function (_super) {
168
- __extends(PipelineLogicError, _super);
169
- function PipelineLogicError(message) {
170
- var _this = _super.call(this, message) || this;
171
- _this.name = 'PipelineLogicError';
172
- Object.setPrototypeOf(_this, PipelineLogicError.prototype);
173
- return _this;
174
- }
175
- return PipelineLogicError;
176
- }(Error));
177
-
178
- /**
179
- * Function `renamePipelineParameter` will find all usable parameters for given task
180
- * In other words, it will find all parameters that are not used in the task itseld and all its dependencies
157
+ * 1) Leveling indentation
158
+ * 2) Putting always-true or always-false conditions without getting eslint errors
181
159
  *
182
- * @throws {PipelineLogicError} If the new parameter name is already used in the pipeline
183
- * @public exported from `@promptbook/editable`
160
+ * @param value any values
161
+ * @returns the same values
162
+ * @private within the repository
184
163
  */
185
- function renamePipelineParameter(options) {
186
- var e_1, _a, e_2, _b;
187
- var pipeline = options.pipeline, oldParameterName = options.oldParameterName, newParameterName = options.newParameterName;
188
- if (pipeline.parameters.some(function (parameter) { return parameter.name === newParameterName; })) {
189
- throw new PipelineLogicError("Can not replace {".concat(oldParameterName, "} to {").concat(newParameterName, "} because {").concat(newParameterName, "} is already used in the pipeline"));
190
- }
191
- var renamedPipeline = __assign(__assign({}, pipeline), {
192
- // <- TODO: [🪓] This should be without `as $PipelineJson`
193
- parameters: __spreadArray([], __read(pipeline.parameters), false), tasks: __spreadArray([], __read(pipeline.tasks), false) });
194
- try {
195
- for (var _c = __values(renamedPipeline.parameters), _d = _c.next(); !_d.done; _d = _c.next()) {
196
- var parameter = _d.value;
197
- if (parameter.name !== oldParameterName) {
198
- continue;
199
- }
200
- parameter.name = newParameterName;
201
- }
202
- }
203
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
204
- finally {
205
- try {
206
- if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
207
- }
208
- finally { if (e_1) throw e_1.error; }
209
- }
210
- try {
211
- for (var _e = __values(renamedPipeline.tasks), _f = _e.next(); !_f.done; _f = _e.next()) {
212
- var task = _f.value;
213
- if (task.resultingParameterName === oldParameterName) {
214
- task.resultingParameterName = newParameterName;
215
- }
216
- task.dependentParameterNames = task.dependentParameterNames.map(function (dependentParameterName) {
217
- return dependentParameterName === oldParameterName ? newParameterName : dependentParameterName;
218
- });
219
- task.content = task.content.replace(new RegExp("{".concat(oldParameterName, "}"), 'g'), "{".concat(newParameterName, "}"));
220
- task.title = task.title.replace(new RegExp("{".concat(oldParameterName, "}"), 'g'), "{".concat(newParameterName, "}"));
221
- task.description =
222
- task.description === undefined
223
- ? undefined
224
- : task.description.replace(new RegExp("{".concat(oldParameterName, "}"), 'g'), "{".concat(newParameterName, "}"));
225
- }
226
- }
227
- catch (e_2_1) { e_2 = { error: e_2_1 }; }
228
- finally {
229
- try {
230
- if (_f && !_f.done && (_b = _e.return)) _b.call(_e);
231
- }
232
- finally { if (e_2) throw e_2.error; }
164
+ function just(value) {
165
+ if (value === undefined) {
166
+ return undefined;
233
167
  }
234
- return renamedPipeline;
168
+ return value;
235
169
  }
236
170
 
237
171
  /**
@@ -254,6 +188,12 @@
254
188
  * @public exported from `@promptbook/core`
255
189
  */
256
190
  var ADMIN_GITHUB_NAME = 'hejny';
191
+ /**
192
+ * When the title is not provided, the default title is used
193
+ *
194
+ * @public exported from `@promptbook/core`
195
+ */
196
+ var DEFAULT_BOOK_TITLE = "\u2728 Untitled Book";
257
197
  // <- TODO: [🧠] Better system for generator warnings - not always "code" and "by `@promptbook/cli`"
258
198
  /**
259
199
  * The maximum number of iterations for a loops
@@ -278,56 +218,6 @@
278
218
  * TODO: [🧠][🧜‍♂️] Maybe join remoteUrl and path into single value
279
219
  */
280
220
 
281
- /**
282
- * Orders JSON object by keys
283
- *
284
- * @returns The same type of object as the input re-ordered
285
- * @public exported from `@promptbook/utils`
286
- */
287
- function orderJson(options) {
288
- var value = options.value, order = options.order;
289
- var orderedValue = __assign(__assign({}, (order === undefined ? {} : Object.fromEntries(order.map(function (key) { return [key, undefined]; })))), value);
290
- return orderedValue;
291
- }
292
-
293
- /**
294
- * Freezes the given object and all its nested objects recursively
295
- *
296
- * Note: `$` is used to indicate that this function is not a pure function - it mutates given object
297
- * Note: This function mutates the object and returns the original (but mutated-deep-freezed) object
298
- *
299
- * @returns The same object as the input, but deeply frozen
300
- * @public exported from `@promptbook/utils`
301
- */
302
- function $deepFreeze(objectValue) {
303
- var e_1, _a;
304
- if (Array.isArray(objectValue)) {
305
- return Object.freeze(objectValue.map(function (item) { return $deepFreeze(item); }));
306
- }
307
- var propertyNames = Object.getOwnPropertyNames(objectValue);
308
- try {
309
- for (var propertyNames_1 = __values(propertyNames), propertyNames_1_1 = propertyNames_1.next(); !propertyNames_1_1.done; propertyNames_1_1 = propertyNames_1.next()) {
310
- var propertyName = propertyNames_1_1.value;
311
- var value = objectValue[propertyName];
312
- if (value && typeof value === 'object') {
313
- $deepFreeze(value);
314
- }
315
- }
316
- }
317
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
318
- finally {
319
- try {
320
- if (propertyNames_1_1 && !propertyNames_1_1.done && (_a = propertyNames_1.return)) _a.call(propertyNames_1);
321
- }
322
- finally { if (e_1) throw e_1.error; }
323
- }
324
- Object.freeze(objectValue);
325
- return objectValue;
326
- }
327
- /**
328
- * TODO: [🧠] Is there a way how to meaningfully test this utility
329
- */
330
-
331
221
  /**
332
222
  * Make error report URL for the given error
333
223
  *
@@ -363,216 +253,3894 @@
363
253
  }(Error));
364
254
 
365
255
  /**
366
- * Checks if the value is [🚉] serializable as JSON
367
- * If not, throws an UnexpectedError with a rich error message and tracking
368
- *
369
- * - Almost all primitives are serializable BUT:
370
- * - `undefined` is not serializable
371
- * - `NaN` is not serializable
372
- * - Objects and arrays are serializable if all their properties are serializable
373
- * - Functions are not serializable
374
- * - Circular references are not serializable
375
- * - `Date` objects are not serializable
376
- * - `Map` and `Set` objects are not serializable
377
- * - `RegExp` objects are not serializable
378
- * - `Error` objects are not serializable
379
- * - `Symbol` objects are not serializable
380
- * - And much more...
256
+ * This error indicates that the promptbook in a markdown format cannot be parsed into a valid promptbook object
381
257
  *
382
- * @throws UnexpectedError if the value is not serializable as JSON
383
- * @public exported from `@promptbook/utils`
258
+ * @public exported from `@promptbook/core`
384
259
  */
385
- function checkSerializableAsJson(options) {
386
- var e_1, _a;
387
- var value = options.value, name = options.name, message = options.message;
388
- if (value === undefined) {
389
- throw new UnexpectedError("".concat(name, " is undefined"));
390
- }
391
- else if (value === null) {
392
- return;
393
- }
394
- else if (typeof value === 'boolean') {
395
- return;
260
+ var ParseError = /** @class */ (function (_super) {
261
+ __extends(ParseError, _super);
262
+ function ParseError(message) {
263
+ var _this = _super.call(this, message) || this;
264
+ _this.name = 'ParseError';
265
+ Object.setPrototypeOf(_this, ParseError.prototype);
266
+ return _this;
396
267
  }
397
- else if (typeof value === 'number' && !isNaN(value)) {
398
- return;
268
+ return ParseError;
269
+ }(Error));
270
+ /**
271
+ * TODO: Maybe split `ParseError` and `ApplyError`
272
+ */
273
+
274
+ /**
275
+ * Parses the boilerplate command
276
+ *
277
+ * Note: @@@ This command is used as boilerplate for new commands - it should NOT be used in any `.book.md` file
278
+ *
279
+ * @see `documentationUrl` for more details
280
+ * @private within the commands folder
281
+ */
282
+ var boilerplateCommandParser = {
283
+ /**
284
+ * Name of the command
285
+ */
286
+ name: 'BOILERPLATE',
287
+ /**
288
+ * Aliases for the BOILERPLATE command
289
+ */
290
+ aliasNames: ['BP'],
291
+ /**
292
+ * BOILERPLATE command can be used in:
293
+ */
294
+ isUsedInPipelineHead: true,
295
+ isUsedInPipelineTask: true,
296
+ /**
297
+ * Description of the BOILERPLATE command
298
+ */
299
+ description: "@@",
300
+ /**
301
+ * Link to documentation
302
+ */
303
+ documentationUrl: 'https://github.com/webgptorg/promptbook/discussions/@@',
304
+ /**
305
+ * Example usages of the BOILERPLATE command
306
+ */
307
+ examples: ['BOILERPLATE foo', 'BOILERPLATE bar', 'BP foo', 'BP bar'],
308
+ /**
309
+ * Parses the BOILERPLATE command
310
+ */
311
+ parse: function (input) {
312
+ var args = input.args;
313
+ if (args.length !== 1) {
314
+ throw new ParseError("BOILERPLATE command requires exactly one argument");
315
+ }
316
+ var value = args[0].toLowerCase();
317
+ if (value.includes('brr')) {
318
+ throw new ParseError("BOILERPLATE value can not contain brr");
319
+ }
320
+ return {
321
+ type: 'BOILERPLATE',
322
+ value: value,
323
+ };
324
+ },
325
+ /**
326
+ * Apply the BOILERPLATE command to the `pipelineJson`
327
+ *
328
+ * Note: `$` is used to indicate that this function mutates given `pipelineJson`
329
+ */
330
+ $applyToPipelineJson: function (command, $pipelineJson) {
331
+ throw new ParseError("BOILERPLATE command is only for testing purposes and should not be used in the .book.md file");
332
+ },
333
+ /**
334
+ * Apply the BOILERPLATE command to the `pipelineJson`
335
+ *
336
+ * Note: `$` is used to indicate that this function mutates given `taskJson`
337
+ */
338
+ $applyToTaskJson: function (command, $taskJson, $pipelineJson) {
339
+ throw new ParseError("BOILERPLATE command is only for testing purposes and should not be used in the .book.md file");
340
+ },
341
+ /**
342
+ * Converts the BOILERPLATE command back to string
343
+ *
344
+ * Note: This is used in `pipelineJsonToString` utility
345
+ */
346
+ stringify: function (command) {
347
+ return "---"; // <- TODO: [🛋] Implement
348
+ },
349
+ /**
350
+ * Reads the BOILERPLATE command from the `PipelineJson`
351
+ *
352
+ * Note: This is used in `pipelineJsonToString` utility
353
+ */
354
+ takeFromPipelineJson: function (pipelineJson) {
355
+ throw new ParseError("BOILERPLATE command is only for testing purposes and should not be used in the .book.md file");
356
+ },
357
+ /**
358
+ * Reads the BOILERPLATE command from the `TaskJson`
359
+ *
360
+ * Note: This is used in `pipelineJsonToString` utility
361
+ */
362
+ takeFromTaskJson: function ($taskJson) {
363
+ throw new ParseError("BOILERPLATE command is only for testing purposes and should not be used in the .book.md file");
364
+ },
365
+ };
366
+
367
+ /**
368
+ * This error type indicates that some part of the code is not implemented yet
369
+ *
370
+ * @public exported from `@promptbook/core`
371
+ */
372
+ var NotYetImplementedError = /** @class */ (function (_super) {
373
+ __extends(NotYetImplementedError, _super);
374
+ function NotYetImplementedError(message) {
375
+ var _this = _super.call(this, spaceTrim.spaceTrim(function (block) { return "\n ".concat(block(message), "\n\n Note: This feature is not implemented yet but it will be soon.\n\n If you want speed up the implementation or just read more, look here:\n https://github.com/webgptorg/promptbook\n\n Or contact us on me@pavolhejny.com\n\n "); })) || this;
376
+ _this.name = 'NotYetImplementedError';
377
+ Object.setPrototypeOf(_this, NotYetImplementedError.prototype);
378
+ return _this;
399
379
  }
400
- else if (typeof value === 'string') {
401
- return;
380
+ return NotYetImplementedError;
381
+ }(Error));
382
+
383
+ /**
384
+ * Tests if given string is valid semantic version
385
+ *
386
+ * Note: There are two simmilar functions:
387
+ * - `isValidSemanticVersion` which tests any semantic version
388
+ * - `isValidPromptbookVersion` *(this one)* which tests just Promptbook versions
389
+ *
390
+ * @public exported from `@promptbook/utils`
391
+ */
392
+ function isValidSemanticVersion(version) {
393
+ if (typeof version !== 'string') {
394
+ return false;
402
395
  }
403
- else if (typeof value === 'symbol') {
404
- throw new UnexpectedError("".concat(name, " is symbol"));
396
+ if (version.startsWith('0.0.0')) {
397
+ return false;
405
398
  }
406
- else if (typeof value === 'function') {
407
- throw new UnexpectedError("".concat(name, " is function"));
399
+ return /^\d+\.\d+\.\d+(-\d+)?$/i.test(version);
400
+ }
401
+
402
+ /**
403
+ * Tests if given string is valid promptbook version
404
+ * It looks into list of known promptbook versions.
405
+ *
406
+ * @see https://www.npmjs.com/package/promptbook?activeTab=versions
407
+ * Note: When you are using for example promptbook 2.0.0 and there already is promptbook 3.0.0 it don`t know about it.
408
+ * Note: There are two simmilar functions:
409
+ * - `isValidSemanticVersion` which tests any semantic version
410
+ * - `isValidPromptbookVersion` *(this one)* which tests just Promptbook versions
411
+ *
412
+ * @public exported from `@promptbook/utils`
413
+ */
414
+ function isValidPromptbookVersion(version) {
415
+ if (!isValidSemanticVersion(version)) {
416
+ return false;
408
417
  }
409
- else if (typeof value === 'object' && Array.isArray(value)) {
410
- for (var i = 0; i < value.length; i++) {
411
- checkSerializableAsJson({ name: "".concat(name, "[").concat(i, "]"), value: value[i], message: message });
412
- }
418
+ if ( /* version === '1.0.0' || */version === '2.0.0' || version === '3.0.0') {
419
+ return false;
413
420
  }
414
- else if (typeof value === 'object') {
415
- if (value instanceof Date) {
416
- throw new UnexpectedError(spaceTrim__default["default"](function (block) { return "\n `".concat(name, "` is Date\n\n Use `string_date_iso8601` instead\n\n Additional message for `").concat(name, "`:\n ").concat(block(message || '(nothing)'), "\n "); }));
421
+ // <- TODO: [main] !!3 Check isValidPromptbookVersion against PROMPTBOOK_ENGINE_VERSIONS
422
+ return true;
423
+ }
424
+
425
+ /**
426
+ * Parses the BOOK_VERSION command
427
+ *
428
+ * @see `documentationUrl` for more details
429
+ * @public exported from `@promptbook/editable`
430
+ */
431
+ var bookVersionCommandParser = {
432
+ /**
433
+ * Name of the command
434
+ */
435
+ name: 'BOOK_VERSION',
436
+ aliasNames: ['PTBK_VERSION', 'PROMPTBOOK_VERSION', 'BOOK'],
437
+ /**
438
+ * BOILERPLATE command can be used in:
439
+ */
440
+ isUsedInPipelineHead: true,
441
+ isUsedInPipelineTask: false,
442
+ /**
443
+ * Description of the BOOK_VERSION command
444
+ */
445
+ description: "Which version of the Book language is the .book.md using",
446
+ /**
447
+ * Link to documentation
448
+ */
449
+ documentationUrl: 'https://github.com/webgptorg/promptbook/discussions/69',
450
+ /**
451
+ * Example usages of the BOOK_VERSION command
452
+ */
453
+ examples: ["BOOK VERSION ".concat(BOOK_LANGUAGE_VERSION), "BOOK ".concat(BOOK_LANGUAGE_VERSION)],
454
+ /**
455
+ * Parses the BOOK_VERSION command
456
+ */
457
+ parse: function (input) {
458
+ var args = input.args;
459
+ var bookVersion = args.pop();
460
+ if (bookVersion === undefined) {
461
+ throw new ParseError("Version is required");
417
462
  }
418
- else if (value instanceof Map) {
419
- throw new UnexpectedError("".concat(name, " is Map"));
463
+ if (!isValidPromptbookVersion(bookVersion)) {
464
+ throw new ParseError("Invalid Promptbook version \"".concat(bookVersion, "\""));
420
465
  }
421
- else if (value instanceof Set) {
422
- throw new UnexpectedError("".concat(name, " is Set"));
466
+ if (args.length > 0 && !(((args.length === 1 && args[0]) || '').toUpperCase() === 'VERSION')) {
467
+ throw new ParseError("Can not have more than one Promptbook version");
423
468
  }
424
- else if (value instanceof RegExp) {
425
- throw new UnexpectedError("".concat(name, " is RegExp"));
469
+ return {
470
+ type: 'BOOK_VERSION',
471
+ bookVersion: bookVersion,
472
+ };
473
+ },
474
+ /**
475
+ * Apply the BOOK_VERSION command to the `pipelineJson`
476
+ *
477
+ * Note: `$` is used to indicate that this function mutates given `pipelineJson`
478
+ */
479
+ $applyToPipelineJson: function (command, $pipelineJson) {
480
+ // TODO: Warn if the version is overridden
481
+ $pipelineJson.bookVersion = command.bookVersion;
482
+ },
483
+ /**
484
+ * Converts the BOOK_VERSION command back to string
485
+ *
486
+ * Note: This is used in `pipelineJsonToString` utility
487
+ */
488
+ stringify: function (command) {
489
+ return "---"; // <- TODO: [🛋] Implement
490
+ },
491
+ /**
492
+ * Reads the BOOK_VERSION command from the `PipelineJson`
493
+ *
494
+ * Note: This is used in `pipelineJsonToString` utility
495
+ */
496
+ takeFromPipelineJson: function (pipelineJson) {
497
+ throw new NotYetImplementedError("[\uD83D\uDECB] Not implemented yet"); // <- TODO: [🛋] Implement
498
+ },
499
+ };
500
+
501
+ /**
502
+ * Units of text measurement
503
+ *
504
+ * @see https://github.com/webgptorg/promptbook/discussions/30
505
+ * @public exported from `@promptbook/core`
506
+ */
507
+ var EXPECTATION_UNITS = ['CHARACTERS', 'WORDS', 'SENTENCES', 'LINES', 'PARAGRAPHS', 'PAGES'];
508
+ /**
509
+ * TODO: [💝] Unite object for expecting amount and format - remove format
510
+ */
511
+
512
+ /**
513
+ * Function parseNumber will parse number from string
514
+ *
515
+ * Unlike Number.parseInt, Number.parseFloat it will never ever result in NaN
516
+ * Note: it also works only with decimal numbers
517
+ *
518
+ * @returns parsed number
519
+ * @throws {ParseError} if the value is not a number
520
+ *
521
+ * @public exported from `@promptbook/utils`
522
+ */
523
+ function parseNumber(value) {
524
+ var originalValue = value;
525
+ if (typeof value === 'number') {
526
+ value = value.toString(); // <- TODO: Maybe more efficient way to do this
527
+ }
528
+ if (typeof value !== 'string') {
529
+ return 0;
530
+ }
531
+ value = value.trim();
532
+ if (value.startsWith('+')) {
533
+ return parseNumber(value.substring(1));
534
+ }
535
+ if (value.startsWith('-')) {
536
+ var number = parseNumber(value.substring(1));
537
+ if (number === 0) {
538
+ return 0; // <- Note: To prevent -0
426
539
  }
427
- else if (value instanceof Error) {
428
- throw new UnexpectedError(spaceTrim__default["default"](function (block) { return "\n `".concat(name, "` is unserialized Error\n\n Use function `serializeError`\n\n Additional message for `").concat(name, "`:\n ").concat(block(message || '(nothing)'), "\n\n "); }));
540
+ return -number;
541
+ }
542
+ value = value.replace(/,/g, '.');
543
+ value = value.toUpperCase();
544
+ if (value === '') {
545
+ return 0;
546
+ }
547
+ if (value === '♾' || value.startsWith('INF')) {
548
+ return Infinity;
549
+ }
550
+ if (value.includes('/')) {
551
+ var _a = __read(value.split('/'), 2), numerator_ = _a[0], denominator_ = _a[1];
552
+ var numerator = parseNumber(numerator_);
553
+ var denominator = parseNumber(denominator_);
554
+ if (denominator === 0) {
555
+ throw new ParseError("Unable to parse number from \"".concat(originalValue, "\" because denominator is zero"));
429
556
  }
430
- else {
557
+ return numerator / denominator;
558
+ }
559
+ if (/^(NAN|NULL|NONE|UNDEFINED|ZERO|NO.*)$/.test(value)) {
560
+ return 0;
561
+ }
562
+ if (value.includes('E')) {
563
+ var _b = __read(value.split('E'), 2), significand = _b[0], exponent = _b[1];
564
+ return parseNumber(significand) * Math.pow(10, parseNumber(exponent));
565
+ }
566
+ if (!/^[0-9.]+$/.test(value) || value.split('.').length > 2) {
567
+ throw new ParseError("Unable to parse number from \"".concat(originalValue, "\""));
568
+ }
569
+ var num = parseFloat(value);
570
+ if (isNaN(num)) {
571
+ throw new ParseError("Unexpected NaN when parsing number from \"".concat(originalValue, "\""));
572
+ }
573
+ return num;
574
+ }
575
+ /**
576
+ * TODO: Maybe use sth. like safe-eval in fraction/calculation case @see https://www.npmjs.com/package/safe-eval
577
+ * TODO: [🧠][🌻] Maybe export through `@promptbook/markdown-utils` not `@promptbook/utils`
578
+ */
579
+
580
+ /**
581
+ * Parses the expect command
582
+ *
583
+ * @see `documentationUrl` for more details
584
+ * @public exported from `@promptbook/editable`
585
+ */
586
+ var expectCommandParser = {
587
+ /**
588
+ * Name of the command
589
+ */
590
+ name: 'EXPECT',
591
+ /**
592
+ * BOILERPLATE command can be used in:
593
+ */
594
+ isUsedInPipelineHead: false,
595
+ isUsedInPipelineTask: true,
596
+ /**
597
+ * Description of the FORMAT command
598
+ */
599
+ description: spaceTrim__default["default"]("\n Expect command describes the desired output of the task *(after post-processing)*\n It can set limits for the maximum/minimum length of the output, measured in characters, words, sentences, paragraphs or some other shape of the output.\n "),
600
+ /**
601
+ * Link to documentation
602
+ */
603
+ documentationUrl: 'https://github.com/webgptorg/promptbook/discussions/30',
604
+ /**
605
+ * Example usages of the FORMAT command
606
+ */
607
+ examples: [
608
+ 'EXPECT MIN 100 Characters',
609
+ 'EXPECT MAX 10 Words',
610
+ 'EXPECT EXACTLY 3 Sentences',
611
+ 'EXPECT EXACTLY 1 Paragraph',
612
+ // <- TODO: 'EXPECT 1 Paragraph',
613
+ ],
614
+ /**
615
+ * Parses the FORMAT command
616
+ */
617
+ parse: function (input) {
618
+ var e_1, _a;
619
+ var args = input.args;
620
+ try {
621
+ var sign = void 0;
622
+ var signRaw = args.shift();
623
+ if (/^exact/i.test(signRaw)) {
624
+ sign = 'EXACTLY';
625
+ }
626
+ else if (/^min/i.test(signRaw)) {
627
+ sign = 'MINIMUM';
628
+ }
629
+ else if (/^max/i.test(signRaw)) {
630
+ sign = 'MAXIMUM';
631
+ }
632
+ else {
633
+ throw new ParseError("Invalid sign \"".concat(signRaw, "\", expected EXACTLY, MIN or MAX"));
634
+ }
635
+ var amountRaw = args.shift();
636
+ var amount = parseNumber(amountRaw);
637
+ if (amount < 0) {
638
+ throw new ParseError('Amount must be positive number or zero');
639
+ }
640
+ if (amount !== Math.floor(amount)) {
641
+ throw new ParseError('Amount must be whole number');
642
+ }
643
+ var unitRaw = args.shift();
644
+ var unit = undefined;
431
645
  try {
432
- for (var _b = __values(Object.entries(value)), _c = _b.next(); !_c.done; _c = _b.next()) {
433
- var _d = __read(_c.value, 2), subName = _d[0], subValue = _d[1];
434
- if (subValue === undefined) {
435
- // Note: undefined in object is serializable - it is just omited
436
- continue;
646
+ 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()) {
647
+ var existingUnit = EXPECTATION_UNITS_1_1.value;
648
+ var existingUnitText = existingUnit;
649
+ existingUnitText = existingUnitText.substring(0, existingUnitText.length - 1);
650
+ if (existingUnitText === 'CHARACTER') {
651
+ existingUnitText = 'CHAR';
652
+ }
653
+ if (new RegExp("^".concat(existingUnitText.toLowerCase())).test(unitRaw.toLowerCase()) ||
654
+ new RegExp("^".concat(unitRaw.toLowerCase())).test(existingUnitText.toLowerCase())) {
655
+ if (unit !== undefined) {
656
+ throw new ParseError("Ambiguous unit \"".concat(unitRaw, "\""));
657
+ }
658
+ unit = existingUnit;
437
659
  }
438
- checkSerializableAsJson({ name: "".concat(name, ".").concat(subName), value: subValue, message: message });
439
660
  }
440
661
  }
441
662
  catch (e_1_1) { e_1 = { error: e_1_1 }; }
442
663
  finally {
443
664
  try {
444
- if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
665
+ if (EXPECTATION_UNITS_1_1 && !EXPECTATION_UNITS_1_1.done && (_a = EXPECTATION_UNITS_1.return)) _a.call(EXPECTATION_UNITS_1);
445
666
  }
446
667
  finally { if (e_1) throw e_1.error; }
447
668
  }
448
- try {
449
- JSON.stringify(value); // <- TODO: [0]
669
+ if (unit === undefined) {
670
+ throw new ParseError("Invalid unit \"".concat(unitRaw, "\""));
450
671
  }
451
- catch (error) {
452
- if (!(error instanceof Error)) {
453
- throw error;
454
- }
455
- throw new UnexpectedError(spaceTrim__default["default"](function (block) { return "\n `".concat(name, "` is not serializable\n\n ").concat(block(error.stack || error.message), "\n\n Additional message for `").concat(name, "`:\n ").concat(block(message || '(nothing)'), "\n "); }));
672
+ return {
673
+ type: 'EXPECT',
674
+ sign: sign,
675
+ unit: unit,
676
+ amount: amount,
677
+ };
678
+ }
679
+ catch (error) {
680
+ if (!(error instanceof Error)) {
681
+ throw error;
456
682
  }
457
- /*
458
- TODO: [0] Is there some more elegant way to check circular references?
459
- const seen = new Set();
460
- const stack = [{ value }];
461
- while (stack.length > 0) {
462
- const { value } = stack.pop()!;
463
- if (typeof value === 'object' && value !== null) {
464
- if (seen.has(value)) {
465
- throw new UnexpectedError(`${name} has circular reference`);
466
- }
467
- seen.add(value);
468
- if (Array.isArray(value)) {
469
- stack.push(...value.map((value) => ({ value })));
470
- } else {
471
- stack.push(...Object.values(value).map((value) => ({ value })));
472
- }
473
- }
683
+ throw new ParseError(spaceTrim__default["default"](function (block) {
684
+ return "\n Invalid FORMAT command\n ".concat(block(error.message), ":\n ");
685
+ }));
686
+ }
687
+ },
688
+ /**
689
+ * Apply the FORMAT command to the `pipelineJson`
690
+ *
691
+ * Note: `$` is used to indicate that this function mutates given `taskJson`
692
+ */
693
+ $applyToTaskJson: function (command, $taskJson) {
694
+ // eslint-disable-next-line no-case-declarations
695
+ var unit = command.unit.toLowerCase();
696
+ $taskJson.expectations = $taskJson.expectations || {};
697
+ $taskJson.expectations[unit] = $taskJson.expectations[unit] || {};
698
+ if (command.sign === 'MINIMUM' || command.sign === 'EXACTLY') {
699
+ if ($taskJson.expectations[unit].min !== undefined) {
700
+ throw new ParseError("Already defined minumum ".concat($taskJson.expectations[unit].min, " ").concat(command.unit.toLowerCase(), ", now trying to redefine it to ").concat(command.amount));
474
701
  }
475
- */
476
- return;
702
+ $taskJson.expectations[unit].min = command.amount;
703
+ } /* not else */
704
+ if (command.sign === 'MAXIMUM' || command.sign === 'EXACTLY') {
705
+ if ($taskJson.expectations[unit].max !== undefined) {
706
+ throw new ParseError("Already defined maximum ".concat($taskJson.expectations[unit].max, " ").concat(command.unit.toLowerCase(), ", now trying to redefine it to ").concat(command.amount));
707
+ }
708
+ $taskJson.expectations[unit].max = command.amount;
477
709
  }
710
+ },
711
+ /**
712
+ * Converts the FORMAT command back to string
713
+ *
714
+ * Note: This is used in `pipelineJsonToString` utility
715
+ */
716
+ stringify: function (command) {
717
+ return "---"; // <- TODO: [🛋] Implement
718
+ },
719
+ /**
720
+ * Reads the FORMAT command from the `TaskJson`
721
+ *
722
+ * Note: This is used in `pipelineJsonToString` utility
723
+ */
724
+ takeFromTaskJson: function ($taskJson) {
725
+ throw new NotYetImplementedError("[\uD83D\uDECB] Not implemented yet"); // <- TODO: [🛋] Implement
726
+ },
727
+ };
728
+
729
+ /**
730
+ * This error indicates problems parsing the format value
731
+ *
732
+ * For example, when the format value is not a valid JSON or CSV
733
+ * This is not thrown directly but in extended classes
734
+ *
735
+ * @public exported from `@promptbook/core`
736
+ */
737
+ var AbstractFormatError = /** @class */ (function (_super) {
738
+ __extends(AbstractFormatError, _super);
739
+ // Note: To allow instanceof do not put here error `name`
740
+ // public readonly name = 'AbstractFormatError';
741
+ function AbstractFormatError(message) {
742
+ var _this = _super.call(this, message) || this;
743
+ Object.setPrototypeOf(_this, AbstractFormatError.prototype);
744
+ return _this;
478
745
  }
479
- else {
480
- throw new UnexpectedError(spaceTrim__default["default"](function (block) { return "\n `".concat(name, "` is unknown type\n\n Additional message for `").concat(name, "`:\n ").concat(block(message || '(nothing)'), "\n "); }));
481
- }
482
- }
746
+ return AbstractFormatError;
747
+ }(Error));
748
+
483
749
  /**
484
- * TODO: Can be return type more type-safe? like `asserts options.value is JsonValue`
485
- * TODO: [🧠][main] !!3 In-memory cache of same values to prevent multiple checks
486
- * Note: [🐠] This is how `checkSerializableAsJson` + `isSerializableAsJson` together can just retun true/false or rich error message
750
+ * This error indicates problem with parsing of CSV
751
+ *
752
+ * @public exported from `@promptbook/core`
487
753
  */
754
+ var CsvFormatError = /** @class */ (function (_super) {
755
+ __extends(CsvFormatError, _super);
756
+ function CsvFormatError(message) {
757
+ var _this = _super.call(this, message) || this;
758
+ _this.name = 'CsvFormatError';
759
+ Object.setPrototypeOf(_this, CsvFormatError.prototype);
760
+ return _this;
761
+ }
762
+ return CsvFormatError;
763
+ }(AbstractFormatError));
488
764
 
489
765
  /**
490
766
  * @@@
491
767
  *
768
+ * @public exported from `@promptbook/core`
769
+ */
770
+ var MANDATORY_CSV_SETTINGS = Object.freeze({
771
+ header: true,
772
+ // encoding: 'utf-8',
773
+ });
774
+
775
+ /**
776
+ * Definition for CSV spreadsheet
777
+ *
778
+ * @public exported from `@promptbook/core`
779
+ * <- TODO: [🏢] Export from package `@promptbook/csv`
780
+ */
781
+ var CsvFormatDefinition = {
782
+ formatName: 'CSV',
783
+ aliases: ['SPREADSHEET', 'TABLE'],
784
+ isValid: function (value, settings, schema) {
785
+ return true;
786
+ },
787
+ canBeValid: function (partialValue, settings, schema) {
788
+ return true;
789
+ },
790
+ heal: function (value, settings, schema) {
791
+ throw new Error('Not implemented');
792
+ },
793
+ subvalueDefinitions: [
794
+ {
795
+ subvalueName: 'ROW',
796
+ mapValues: function (value, outputParameterName, settings, mapCallback) {
797
+ return __awaiter(this, void 0, void 0, function () {
798
+ var csv, mappedData;
799
+ var _this = this;
800
+ return __generator(this, function (_a) {
801
+ switch (_a.label) {
802
+ case 0:
803
+ csv = papaparse.parse(value, __assign(__assign({}, settings), MANDATORY_CSV_SETTINGS));
804
+ if (csv.errors.length !== 0) {
805
+ throw new CsvFormatError(spaceTrim__default["default"](function (block) { return "\n CSV parsing error\n\n Error(s) from CSV parsing:\n ".concat(block(csv.errors.map(function (error) { return error.message; }).join('\n\n')), "\n\n The CSV setings:\n ").concat(block(JSON.stringify(__assign(__assign({}, settings), MANDATORY_CSV_SETTINGS), null, 2)), "\n\n The CSV data:\n ").concat(block(value), "\n "); }));
806
+ }
807
+ return [4 /*yield*/, Promise.all(csv.data.map(function (row, index) { return __awaiter(_this, void 0, void 0, function () {
808
+ var _a, _b;
809
+ var _c;
810
+ return __generator(this, function (_d) {
811
+ switch (_d.label) {
812
+ case 0:
813
+ if (row[outputParameterName]) {
814
+ throw new CsvFormatError("Can not overwrite existing column \"".concat(outputParameterName, "\" in CSV row"));
815
+ }
816
+ _a = [__assign({}, row)];
817
+ _c = {};
818
+ _b = outputParameterName;
819
+ return [4 /*yield*/, mapCallback(row, index)];
820
+ case 1: return [2 /*return*/, __assign.apply(void 0, _a.concat([(_c[_b] = _d.sent(), _c)]))];
821
+ }
822
+ });
823
+ }); }))];
824
+ case 1:
825
+ mappedData = _a.sent();
826
+ return [2 /*return*/, papaparse.unparse(mappedData, __assign(__assign({}, settings), MANDATORY_CSV_SETTINGS))];
827
+ }
828
+ });
829
+ });
830
+ },
831
+ },
832
+ {
833
+ subvalueName: 'CELL',
834
+ mapValues: function (value, outputParameterName, settings, mapCallback) {
835
+ return __awaiter(this, void 0, void 0, function () {
836
+ var csv, mappedData;
837
+ var _this = this;
838
+ return __generator(this, function (_a) {
839
+ switch (_a.label) {
840
+ case 0:
841
+ csv = papaparse.parse(value, __assign(__assign({}, settings), MANDATORY_CSV_SETTINGS));
842
+ if (csv.errors.length !== 0) {
843
+ throw new CsvFormatError(spaceTrim__default["default"](function (block) { return "\n CSV parsing error\n\n Error(s) from CSV parsing:\n ".concat(block(csv.errors.map(function (error) { return error.message; }).join('\n\n')), "\n\n The CSV setings:\n ").concat(block(JSON.stringify(__assign(__assign({}, settings), MANDATORY_CSV_SETTINGS), null, 2)), "\n\n The CSV data:\n ").concat(block(value), "\n "); }));
844
+ }
845
+ return [4 /*yield*/, Promise.all(csv.data.map(function (row, rowIndex) { return __awaiter(_this, void 0, void 0, function () {
846
+ var _this = this;
847
+ return __generator(this, function (_a) {
848
+ return [2 /*return*/, /* not await */ Promise.all(Object.entries(row).map(function (_a, columnIndex) {
849
+ var _b = __read(_a, 2), key = _b[0], value = _b[1];
850
+ return __awaiter(_this, void 0, void 0, function () {
851
+ var index;
852
+ var _c;
853
+ return __generator(this, function (_d) {
854
+ index = rowIndex * Object.keys(row).length + columnIndex;
855
+ return [2 /*return*/, /* not await */ mapCallback((_c = {}, _c[key] = value, _c), index)];
856
+ });
857
+ });
858
+ }))];
859
+ });
860
+ }); }))];
861
+ case 1:
862
+ mappedData = _a.sent();
863
+ return [2 /*return*/, papaparse.unparse(mappedData, __assign(__assign({}, settings), MANDATORY_CSV_SETTINGS))];
864
+ }
865
+ });
866
+ });
867
+ },
868
+ },
869
+ ],
870
+ };
871
+ /**
872
+ * TODO: [🍓] In `CsvFormatDefinition` implement simple `isValid`
873
+ * TODO: [🍓] In `CsvFormatDefinition` implement partial `canBeValid`
874
+ * TODO: [🍓] In `CsvFormatDefinition` implement `heal
875
+ * TODO: [🍓] In `CsvFormatDefinition` implement `subvalueDefinitions`
876
+ * TODO: [🏢] Allow to expect something inside CSV objects and other formats
877
+ */
878
+
879
+ /**
880
+ * Function isValidJsonString will tell you if the string is valid JSON or not
881
+ *
492
882
  * @public exported from `@promptbook/utils`
493
883
  */
494
- function deepClone(objectValue) {
495
- return JSON.parse(JSON.stringify(objectValue));
496
- /*
497
- TODO: [🧠] Is there a better implementation?
498
- > const propertyNames = Object.getOwnPropertyNames(objectValue);
499
- > for (const propertyName of propertyNames) {
500
- > const value = (objectValue as really_any)[propertyName];
501
- > if (value && typeof value === 'object') {
502
- > deepClone(value);
503
- > }
504
- > }
505
- > return Object.assign({}, objectValue);
506
- */
884
+ function isValidJsonString(value /* <- [👨‍⚖️] */) {
885
+ try {
886
+ JSON.parse(value);
887
+ return true;
888
+ }
889
+ catch (error) {
890
+ if (!(error instanceof Error)) {
891
+ throw error;
892
+ }
893
+ if (error.message.includes('Unexpected token')) {
894
+ return false;
895
+ }
896
+ return false;
897
+ }
507
898
  }
899
+
508
900
  /**
509
- * TODO: [🧠] Is there a way how to meaningfully test this utility
901
+ * Definition for JSON format
902
+ *
903
+ * @private still in development [🏢]
904
+ */
905
+ var JsonFormatDefinition = {
906
+ formatName: 'JSON',
907
+ mimeType: 'application/json',
908
+ isValid: function (value, settings, schema) {
909
+ return isValidJsonString(value);
910
+ },
911
+ canBeValid: function (partialValue, settings, schema) {
912
+ return true;
913
+ },
914
+ heal: function (value, settings, schema) {
915
+ throw new Error('Not implemented');
916
+ },
917
+ subvalueDefinitions: [],
918
+ };
919
+ /**
920
+ * TODO: [🧠] Maybe propper instance of object
921
+ * TODO: [0] Make string_serialized_json
922
+ * TODO: [1] Make type for JSON Settings and Schema
923
+ * TODO: [🧠] What to use for validating JSONs - JSON Schema, ZoD, typescript types/interfaces,...?
924
+ * TODO: [🍓] In `JsonFormatDefinition` implement simple `isValid`
925
+ * TODO: [🍓] In `JsonFormatDefinition` implement partial `canBeValid`
926
+ * TODO: [🍓] In `JsonFormatDefinition` implement `heal
927
+ * TODO: [🍓] In `JsonFormatDefinition` implement `subvalueDefinitions`
928
+ * TODO: [🏢] Allow to expect something inside JSON objects and other formats
510
929
  */
511
930
 
512
931
  /**
513
- * Utility to export a JSON object from a function
932
+ * Definition for any text - this will be always valid
514
933
  *
515
- * 1) Checks if the value is serializable as JSON
516
- * 2) Makes a deep clone of the object
517
- * 2) Orders the object properties
518
- * 2) Deeply freezes the cloned object
934
+ * Note: This is not useful for validation, but for splitting and mapping with `subvalueDefinitions`
519
935
  *
520
- * Note: This function does not mutates the given object
936
+ * @public exported from `@promptbook/core`
937
+ */
938
+ var TextFormatDefinition = {
939
+ formatName: 'TEXT',
940
+ isValid: function (value) {
941
+ return typeof value === 'string';
942
+ },
943
+ canBeValid: function (partialValue) {
944
+ return typeof partialValue === 'string';
945
+ },
946
+ heal: function () {
947
+ throw new UnexpectedError('It does not make sense to call `TextFormatDefinition.heal`');
948
+ },
949
+ subvalueDefinitions: [
950
+ {
951
+ subvalueName: 'LINE',
952
+ mapValues: function (value, outputParameterName, settings, mapCallback) {
953
+ return __awaiter(this, void 0, void 0, function () {
954
+ var lines, mappedLines;
955
+ return __generator(this, function (_a) {
956
+ switch (_a.label) {
957
+ case 0:
958
+ lines = value.split('\n');
959
+ return [4 /*yield*/, Promise.all(lines.map(function (lineContent, lineNumber) {
960
+ // TODO: [🧠] Maybe option to skip empty line
961
+ /* not await */ return mapCallback({
962
+ lineContent: lineContent,
963
+ // TODO: [🧠] Maybe also put here `lineNumber`
964
+ }, lineNumber);
965
+ }))];
966
+ case 1:
967
+ mappedLines = _a.sent();
968
+ return [2 /*return*/, mappedLines.join('\n')];
969
+ }
970
+ });
971
+ });
972
+ },
973
+ },
974
+ // <- TODO: [🧠][🤠] Here should be all words, characters, lines, paragraphs, pages aviable as subvalues
975
+ ],
976
+ };
977
+ /**
978
+ * TODO: [1] Make type for XML Text and Schema
979
+ * TODO: [🧠][🤠] Here should be all words, characters, lines, paragraphs, pages aviable as subvalues
980
+ * TODO: [🍓] In `TextFormatDefinition` implement simple `isValid`
981
+ * TODO: [🍓] In `TextFormatDefinition` implement partial `canBeValid`
982
+ * TODO: [🍓] In `TextFormatDefinition` implement `heal
983
+ * TODO: [🍓] In `TextFormatDefinition` implement `subvalueDefinitions`
984
+ * TODO: [🏢] Allow to expect something inside each item of list and other formats
985
+ */
986
+
987
+ /**
988
+ * Definition for XML format
521
989
  *
522
- * @returns The same type of object as the input but read-only and re-ordered
990
+ * @private still in development [🏢]
991
+ */
992
+ var XmlFormatDefinition = {
993
+ formatName: 'XML',
994
+ mimeType: 'application/xml',
995
+ isValid: function (value, settings, schema) {
996
+ return true;
997
+ },
998
+ canBeValid: function (partialValue, settings, schema) {
999
+ return true;
1000
+ },
1001
+ heal: function (value, settings, schema) {
1002
+ throw new Error('Not implemented');
1003
+ },
1004
+ subvalueDefinitions: [],
1005
+ };
1006
+ /**
1007
+ * TODO: [🧠] Maybe propper instance of object
1008
+ * TODO: [0] Make string_serialized_xml
1009
+ * TODO: [1] Make type for XML Settings and Schema
1010
+ * TODO: [🧠] What to use for validating XMLs - XSD,...
1011
+ * TODO: [🍓] In `XmlFormatDefinition` implement simple `isValid`
1012
+ * TODO: [🍓] In `XmlFormatDefinition` implement partial `canBeValid`
1013
+ * TODO: [🍓] In `XmlFormatDefinition` implement `heal
1014
+ * TODO: [🍓] In `XmlFormatDefinition` implement `subvalueDefinitions`
1015
+ * TODO: [🏢] Allow to expect something inside XML and other formats
1016
+ */
1017
+
1018
+ /**
1019
+ * Definitions for all formats supported by Promptbook
1020
+ *
1021
+ * @private internal index of `...` <- TODO [🏢]
1022
+ */
1023
+ var FORMAT_DEFINITIONS = [
1024
+ JsonFormatDefinition,
1025
+ XmlFormatDefinition,
1026
+ TextFormatDefinition,
1027
+ CsvFormatDefinition,
1028
+ ];
1029
+ /**
1030
+ * Note: [💞] Ignore a discrepancy between file name and entity name
1031
+ */
1032
+
1033
+ /**
1034
+ * @@@
1035
+ *
1036
+ * @param text @@@
1037
+ * @returns @@@
1038
+ * @example 'HELLO_WORLD'
1039
+ * @example 'I_LOVE_PROMPTBOOK'
523
1040
  * @public exported from `@promptbook/utils`
524
1041
  */
525
- function exportJson(options) {
526
- var name = options.name, value = options.value, order = options.order, message = options.message;
527
- checkSerializableAsJson({ name: name, value: value, message: message });
528
- var orderedValue =
529
- // TODO: Fix error "Type instantiation is excessively deep and possibly infinite."
530
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
531
- // @ts-ignore
532
- order === undefined
533
- ? deepClone(value)
534
- : orderJson({
535
- value: value,
536
- // <- Note: checkSerializableAsJson asserts that the value is serializable as JSON
537
- order: order,
538
- });
539
- $deepFreeze(orderedValue);
540
- return orderedValue;
1042
+ function normalizeTo_SCREAMING_CASE(text) {
1043
+ var e_1, _a;
1044
+ var charType;
1045
+ var lastCharType = 'OTHER';
1046
+ var normalizedName = '';
1047
+ try {
1048
+ for (var text_1 = __values(text), text_1_1 = text_1.next(); !text_1_1.done; text_1_1 = text_1.next()) {
1049
+ var char = text_1_1.value;
1050
+ var normalizedChar = void 0;
1051
+ if (/^[a-z]$/.test(char)) {
1052
+ charType = 'LOWERCASE';
1053
+ normalizedChar = char.toUpperCase();
1054
+ }
1055
+ else if (/^[A-Z]$/.test(char)) {
1056
+ charType = 'UPPERCASE';
1057
+ normalizedChar = char;
1058
+ }
1059
+ else if (/^[0-9]$/.test(char)) {
1060
+ charType = 'NUMBER';
1061
+ normalizedChar = char;
1062
+ }
1063
+ else {
1064
+ charType = 'OTHER';
1065
+ normalizedChar = '_';
1066
+ }
1067
+ if (charType !== lastCharType &&
1068
+ !(lastCharType === 'UPPERCASE' && charType === 'LOWERCASE') &&
1069
+ !(lastCharType === 'NUMBER') &&
1070
+ !(charType === 'NUMBER')) {
1071
+ normalizedName += '_';
1072
+ }
1073
+ normalizedName += normalizedChar;
1074
+ lastCharType = charType;
1075
+ }
1076
+ }
1077
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
1078
+ finally {
1079
+ try {
1080
+ if (text_1_1 && !text_1_1.done && (_a = text_1.return)) _a.call(text_1);
1081
+ }
1082
+ finally { if (e_1) throw e_1.error; }
1083
+ }
1084
+ normalizedName = normalizedName.replace(/_+/g, '_');
1085
+ normalizedName = normalizedName.replace(/_?\/_?/g, '/');
1086
+ normalizedName = normalizedName.replace(/^_/, '');
1087
+ normalizedName = normalizedName.replace(/_$/, '');
1088
+ return normalizedName;
541
1089
  }
542
1090
  /**
543
- * TODO: [🧠] Is there a way how to meaningfully test this utility
1091
+ * TODO: Tests
1092
+ * > expect(encodeRoutePath({ uriId: 'VtG7sR9rRJqwNEdM2', name: 'Moje tabule' })).toEqual('/VtG7sR9rRJqwNEdM2/Moje tabule');
1093
+ * > expect(encodeRoutePath({ uriId: 'VtG7sR9rRJqwNEdM2', name: 'ěščřžžýáíúů' })).toEqual('/VtG7sR9rRJqwNEdM2/escrzyaieuu');
1094
+ * > expect(encodeRoutePath({ uriId: 'VtG7sR9rRJqwNEdM2', name: ' ahoj ' })).toEqual('/VtG7sR9rRJqwNEdM2/ahoj');
1095
+ * > expect(encodeRoutePath({ uriId: 'VtG7sR9rRJqwNEdM2', name: ' ahoj_ahojAhoj ahoj ' })).toEqual('/VtG7sR9rRJqwNEdM2/ahoj-ahoj-ahoj-ahoj');
1096
+ * TODO: [🌺] Use some intermediate util splitWords
544
1097
  */
545
1098
 
546
1099
  /**
547
- * Nonce which is used for replacing things in strings
1100
+ * Orders JSON object by keys
548
1101
  *
549
- * @private within the repository
1102
+ * @returns The same type of object as the input re-ordered
1103
+ * @public exported from `@promptbook/utils`
550
1104
  */
551
- var REPLACING_NONCE = 'u$k42k%!V2zo34w7Fu#@QUHYPW';
1105
+ function orderJson(options) {
1106
+ var value = options.value, order = options.order;
1107
+ var orderedValue = __assign(__assign({}, (order === undefined ? {} : Object.fromEntries(order.map(function (key) { return [key, undefined]; })))), value);
1108
+ return orderedValue;
1109
+ }
1110
+
552
1111
  /**
553
- * The names of the parameters that are reserved for special purposes
1112
+ * Freezes the given object and all its nested objects recursively
554
1113
  *
555
- * @public exported from `@promptbook/core`
1114
+ * Note: `$` is used to indicate that this function is not a pure function - it mutates given object
1115
+ * Note: This function mutates the object and returns the original (but mutated-deep-freezed) object
1116
+ *
1117
+ * @returns The same object as the input, but deeply frozen
1118
+ * @public exported from `@promptbook/utils`
556
1119
  */
557
- exportJson({
558
- name: 'RESERVED_PARAMETER_NAMES',
559
- message: "The names of the parameters that are reserved for special purposes",
560
- value: [
561
- 'content',
562
- 'context',
563
- 'knowledge',
564
- 'examples',
565
- 'modelName',
566
- 'currentDate',
567
- // <- TODO: list here all command names
568
- // <- TODO: Add more like 'date', 'modelName',...
569
- // <- TODO: Add [emoji] + instructions ACRY when adding new reserved parameter
570
- ],
571
- });
572
- /**
1120
+ function $deepFreeze(objectValue) {
1121
+ var e_1, _a;
1122
+ if (Array.isArray(objectValue)) {
1123
+ return Object.freeze(objectValue.map(function (item) { return $deepFreeze(item); }));
1124
+ }
1125
+ var propertyNames = Object.getOwnPropertyNames(objectValue);
1126
+ try {
1127
+ for (var propertyNames_1 = __values(propertyNames), propertyNames_1_1 = propertyNames_1.next(); !propertyNames_1_1.done; propertyNames_1_1 = propertyNames_1.next()) {
1128
+ var propertyName = propertyNames_1_1.value;
1129
+ var value = objectValue[propertyName];
1130
+ if (value && typeof value === 'object') {
1131
+ $deepFreeze(value);
1132
+ }
1133
+ }
1134
+ }
1135
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
1136
+ finally {
1137
+ try {
1138
+ if (propertyNames_1_1 && !propertyNames_1_1.done && (_a = propertyNames_1.return)) _a.call(propertyNames_1);
1139
+ }
1140
+ finally { if (e_1) throw e_1.error; }
1141
+ }
1142
+ Object.freeze(objectValue);
1143
+ return objectValue;
1144
+ }
1145
+ /**
1146
+ * TODO: [🧠] Is there a way how to meaningfully test this utility
1147
+ */
1148
+
1149
+ /**
1150
+ * Checks if the value is [🚉] serializable as JSON
1151
+ * If not, throws an UnexpectedError with a rich error message and tracking
1152
+ *
1153
+ * - Almost all primitives are serializable BUT:
1154
+ * - `undefined` is not serializable
1155
+ * - `NaN` is not serializable
1156
+ * - Objects and arrays are serializable if all their properties are serializable
1157
+ * - Functions are not serializable
1158
+ * - Circular references are not serializable
1159
+ * - `Date` objects are not serializable
1160
+ * - `Map` and `Set` objects are not serializable
1161
+ * - `RegExp` objects are not serializable
1162
+ * - `Error` objects are not serializable
1163
+ * - `Symbol` objects are not serializable
1164
+ * - And much more...
1165
+ *
1166
+ * @throws UnexpectedError if the value is not serializable as JSON
1167
+ * @public exported from `@promptbook/utils`
1168
+ */
1169
+ function checkSerializableAsJson(options) {
1170
+ var e_1, _a;
1171
+ var value = options.value, name = options.name, message = options.message;
1172
+ if (value === undefined) {
1173
+ throw new UnexpectedError("".concat(name, " is undefined"));
1174
+ }
1175
+ else if (value === null) {
1176
+ return;
1177
+ }
1178
+ else if (typeof value === 'boolean') {
1179
+ return;
1180
+ }
1181
+ else if (typeof value === 'number' && !isNaN(value)) {
1182
+ return;
1183
+ }
1184
+ else if (typeof value === 'string') {
1185
+ return;
1186
+ }
1187
+ else if (typeof value === 'symbol') {
1188
+ throw new UnexpectedError("".concat(name, " is symbol"));
1189
+ }
1190
+ else if (typeof value === 'function') {
1191
+ throw new UnexpectedError("".concat(name, " is function"));
1192
+ }
1193
+ else if (typeof value === 'object' && Array.isArray(value)) {
1194
+ for (var i = 0; i < value.length; i++) {
1195
+ checkSerializableAsJson({ name: "".concat(name, "[").concat(i, "]"), value: value[i], message: message });
1196
+ }
1197
+ }
1198
+ else if (typeof value === 'object') {
1199
+ if (value instanceof Date) {
1200
+ throw new UnexpectedError(spaceTrim__default["default"](function (block) { return "\n `".concat(name, "` is Date\n\n Use `string_date_iso8601` instead\n\n Additional message for `").concat(name, "`:\n ").concat(block(message || '(nothing)'), "\n "); }));
1201
+ }
1202
+ else if (value instanceof Map) {
1203
+ throw new UnexpectedError("".concat(name, " is Map"));
1204
+ }
1205
+ else if (value instanceof Set) {
1206
+ throw new UnexpectedError("".concat(name, " is Set"));
1207
+ }
1208
+ else if (value instanceof RegExp) {
1209
+ throw new UnexpectedError("".concat(name, " is RegExp"));
1210
+ }
1211
+ else if (value instanceof Error) {
1212
+ throw new UnexpectedError(spaceTrim__default["default"](function (block) { return "\n `".concat(name, "` is unserialized Error\n\n Use function `serializeError`\n\n Additional message for `").concat(name, "`:\n ").concat(block(message || '(nothing)'), "\n\n "); }));
1213
+ }
1214
+ else {
1215
+ try {
1216
+ for (var _b = __values(Object.entries(value)), _c = _b.next(); !_c.done; _c = _b.next()) {
1217
+ var _d = __read(_c.value, 2), subName = _d[0], subValue = _d[1];
1218
+ if (subValue === undefined) {
1219
+ // Note: undefined in object is serializable - it is just omited
1220
+ continue;
1221
+ }
1222
+ checkSerializableAsJson({ name: "".concat(name, ".").concat(subName), value: subValue, message: message });
1223
+ }
1224
+ }
1225
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
1226
+ finally {
1227
+ try {
1228
+ if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
1229
+ }
1230
+ finally { if (e_1) throw e_1.error; }
1231
+ }
1232
+ try {
1233
+ JSON.stringify(value); // <- TODO: [0]
1234
+ }
1235
+ catch (error) {
1236
+ if (!(error instanceof Error)) {
1237
+ throw error;
1238
+ }
1239
+ throw new UnexpectedError(spaceTrim__default["default"](function (block) { return "\n `".concat(name, "` is not serializable\n\n ").concat(block(error.stack || error.message), "\n\n Additional message for `").concat(name, "`:\n ").concat(block(message || '(nothing)'), "\n "); }));
1240
+ }
1241
+ /*
1242
+ TODO: [0] Is there some more elegant way to check circular references?
1243
+ const seen = new Set();
1244
+ const stack = [{ value }];
1245
+ while (stack.length > 0) {
1246
+ const { value } = stack.pop()!;
1247
+ if (typeof value === 'object' && value !== null) {
1248
+ if (seen.has(value)) {
1249
+ throw new UnexpectedError(`${name} has circular reference`);
1250
+ }
1251
+ seen.add(value);
1252
+ if (Array.isArray(value)) {
1253
+ stack.push(...value.map((value) => ({ value })));
1254
+ } else {
1255
+ stack.push(...Object.values(value).map((value) => ({ value })));
1256
+ }
1257
+ }
1258
+ }
1259
+ */
1260
+ return;
1261
+ }
1262
+ }
1263
+ else {
1264
+ throw new UnexpectedError(spaceTrim__default["default"](function (block) { return "\n `".concat(name, "` is unknown type\n\n Additional message for `").concat(name, "`:\n ").concat(block(message || '(nothing)'), "\n "); }));
1265
+ }
1266
+ }
1267
+ /**
1268
+ * TODO: Can be return type more type-safe? like `asserts options.value is JsonValue`
1269
+ * TODO: [🧠][main] !!3 In-memory cache of same values to prevent multiple checks
1270
+ * Note: [🐠] This is how `checkSerializableAsJson` + `isSerializableAsJson` together can just retun true/false or rich error message
1271
+ */
1272
+
1273
+ /**
1274
+ * @@@
1275
+ *
1276
+ * @public exported from `@promptbook/utils`
1277
+ */
1278
+ function deepClone(objectValue) {
1279
+ return JSON.parse(JSON.stringify(objectValue));
1280
+ /*
1281
+ TODO: [🧠] Is there a better implementation?
1282
+ > const propertyNames = Object.getOwnPropertyNames(objectValue);
1283
+ > for (const propertyName of propertyNames) {
1284
+ > const value = (objectValue as really_any)[propertyName];
1285
+ > if (value && typeof value === 'object') {
1286
+ > deepClone(value);
1287
+ > }
1288
+ > }
1289
+ > return Object.assign({}, objectValue);
1290
+ */
1291
+ }
1292
+ /**
1293
+ * TODO: [🧠] Is there a way how to meaningfully test this utility
1294
+ */
1295
+
1296
+ /**
1297
+ * Utility to export a JSON object from a function
1298
+ *
1299
+ * 1) Checks if the value is serializable as JSON
1300
+ * 2) Makes a deep clone of the object
1301
+ * 2) Orders the object properties
1302
+ * 2) Deeply freezes the cloned object
1303
+ *
1304
+ * Note: This function does not mutates the given object
1305
+ *
1306
+ * @returns The same type of object as the input but read-only and re-ordered
1307
+ * @public exported from `@promptbook/utils`
1308
+ */
1309
+ function exportJson(options) {
1310
+ var name = options.name, value = options.value, order = options.order, message = options.message;
1311
+ checkSerializableAsJson({ name: name, value: value, message: message });
1312
+ var orderedValue =
1313
+ // TODO: Fix error "Type instantiation is excessively deep and possibly infinite."
1314
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
1315
+ // @ts-ignore
1316
+ order === undefined
1317
+ ? deepClone(value)
1318
+ : orderJson({
1319
+ value: value,
1320
+ // <- Note: checkSerializableAsJson asserts that the value is serializable as JSON
1321
+ order: order,
1322
+ });
1323
+ $deepFreeze(orderedValue);
1324
+ return orderedValue;
1325
+ }
1326
+ /**
1327
+ * TODO: [🧠] Is there a way how to meaningfully test this utility
1328
+ */
1329
+
1330
+ /**
1331
+ * Nonce which is used for replacing things in strings
1332
+ *
1333
+ * @private within the repository
1334
+ */
1335
+ var REPLACING_NONCE = 'u$k42k%!V2zo34w7Fu#@QUHYPW';
1336
+ /**
1337
+ * The names of the parameters that are reserved for special purposes
1338
+ *
1339
+ * @public exported from `@promptbook/core`
1340
+ */
1341
+ var RESERVED_PARAMETER_NAMES = exportJson({
1342
+ name: 'RESERVED_PARAMETER_NAMES',
1343
+ message: "The names of the parameters that are reserved for special purposes",
1344
+ value: [
1345
+ 'content',
1346
+ 'context',
1347
+ 'knowledge',
1348
+ 'examples',
1349
+ 'modelName',
1350
+ 'currentDate',
1351
+ // <- TODO: list here all command names
1352
+ // <- TODO: Add more like 'date', 'modelName',...
1353
+ // <- TODO: Add [emoji] + instructions ACRY when adding new reserved parameter
1354
+ ],
1355
+ });
1356
+ /**
1357
+ * Note: [💞] Ignore a discrepancy between file name and entity name
1358
+ */
1359
+
1360
+ /**
1361
+ * @@@
1362
+ *
1363
+ * @param text @@@
1364
+ * @param _isFirstLetterCapital @@@
1365
+ * @returns @@@
1366
+ * @example 'helloWorld'
1367
+ * @example 'iLovePromptbook'
1368
+ * @public exported from `@promptbook/utils`
1369
+ */
1370
+ function normalizeTo_camelCase(text, _isFirstLetterCapital) {
1371
+ var e_1, _a;
1372
+ if (_isFirstLetterCapital === void 0) { _isFirstLetterCapital = false; }
1373
+ var charType;
1374
+ var lastCharType = null;
1375
+ var normalizedName = '';
1376
+ try {
1377
+ for (var text_1 = __values(text), text_1_1 = text_1.next(); !text_1_1.done; text_1_1 = text_1.next()) {
1378
+ var char = text_1_1.value;
1379
+ var normalizedChar = void 0;
1380
+ if (/^[a-z]$/.test(char)) {
1381
+ charType = 'LOWERCASE';
1382
+ normalizedChar = char;
1383
+ }
1384
+ else if (/^[A-Z]$/.test(char)) {
1385
+ charType = 'UPPERCASE';
1386
+ normalizedChar = char.toLowerCase();
1387
+ }
1388
+ else if (/^[0-9]$/.test(char)) {
1389
+ charType = 'NUMBER';
1390
+ normalizedChar = char;
1391
+ }
1392
+ else {
1393
+ charType = 'OTHER';
1394
+ normalizedChar = '';
1395
+ }
1396
+ if (!lastCharType) {
1397
+ if (_isFirstLetterCapital) {
1398
+ normalizedChar = normalizedChar.toUpperCase(); //TODO: DRY
1399
+ }
1400
+ }
1401
+ else if (charType !== lastCharType &&
1402
+ !(charType === 'LOWERCASE' && lastCharType === 'UPPERCASE') &&
1403
+ !(lastCharType === 'NUMBER') &&
1404
+ !(charType === 'NUMBER')) {
1405
+ normalizedChar = normalizedChar.toUpperCase(); //TODO: [🌺] DRY
1406
+ }
1407
+ normalizedName += normalizedChar;
1408
+ lastCharType = charType;
1409
+ }
1410
+ }
1411
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
1412
+ finally {
1413
+ try {
1414
+ if (text_1_1 && !text_1_1.done && (_a = text_1.return)) _a.call(text_1);
1415
+ }
1416
+ finally { if (e_1) throw e_1.error; }
1417
+ }
1418
+ return normalizedName;
1419
+ }
1420
+ /**
1421
+ * TODO: [🌺] Use some intermediate util splitWords
1422
+ */
1423
+
1424
+ var defaultDiacriticsRemovalMap = [
1425
+ {
1426
+ base: 'A',
1427
+ letters: '\u0041\u24B6\uFF21\u00C0\u00C1\u00C2\u1EA6\u1EA4\u1EAA\u1EA8\u00C3\u0100\u0102\u1EB0\u1EAE\u1EB4\u1EB2\u0226\u01E0\u00C4\u01DE\u1EA2\u00C5\u01FA\u01CD\u0200\u0202\u1EA0\u1EAC\u1EB6\u1E00\u0104\u023A\u2C6F',
1428
+ },
1429
+ { base: 'AA', letters: '\uA732' },
1430
+ { base: 'AE', letters: '\u00C6\u01FC\u01E2' },
1431
+ { base: 'AO', letters: '\uA734' },
1432
+ { base: 'AU', letters: '\uA736' },
1433
+ { base: 'AV', letters: '\uA738\uA73A' },
1434
+ { base: 'AY', letters: '\uA73C' },
1435
+ {
1436
+ base: 'B',
1437
+ letters: '\u0042\u24B7\uFF22\u1E02\u1E04\u1E06\u0243\u0182\u0181',
1438
+ },
1439
+ {
1440
+ base: 'C',
1441
+ letters: '\u0043\u24B8\uFF23\u0106\u0108\u010A\u010C\u00C7\u1E08\u0187\u023B\uA73E',
1442
+ },
1443
+ {
1444
+ base: 'D',
1445
+ letters: '\u0044\u24B9\uFF24\u1E0A\u010E\u1E0C\u1E10\u1E12\u1E0E\u0110\u018B\u018A\u0189\uA779\u00D0',
1446
+ },
1447
+ { base: 'DZ', letters: '\u01F1\u01C4' },
1448
+ { base: 'Dz', letters: '\u01F2\u01C5' },
1449
+ {
1450
+ base: 'E',
1451
+ letters: '\u0045\u24BA\uFF25\u00C8\u00C9\u00CA\u1EC0\u1EBE\u1EC4\u1EC2\u1EBC\u0112\u1E14\u1E16\u0114\u0116\u00CB\u1EBA\u011A\u0204\u0206\u1EB8\u1EC6\u0228\u1E1C\u0118\u1E18\u1E1A\u0190\u018E',
1452
+ },
1453
+ { base: 'F', letters: '\u0046\u24BB\uFF26\u1E1E\u0191\uA77B' },
1454
+ {
1455
+ base: 'G',
1456
+ letters: '\u0047\u24BC\uFF27\u01F4\u011C\u1E20\u011E\u0120\u01E6\u0122\u01E4\u0193\uA7A0\uA77D\uA77E',
1457
+ },
1458
+ {
1459
+ base: 'H',
1460
+ letters: '\u0048\u24BD\uFF28\u0124\u1E22\u1E26\u021E\u1E24\u1E28\u1E2A\u0126\u2C67\u2C75\uA78D',
1461
+ },
1462
+ {
1463
+ base: 'I',
1464
+ letters: '\u0049\u24BE\uFF29\u00CC\u00CD\u00CE\u0128\u012A\u012C\u0130\u00CF\u1E2E\u1EC8\u01CF\u0208\u020A\u1ECA\u012E\u1E2C\u0197',
1465
+ },
1466
+ { base: 'J', letters: '\u004A\u24BF\uFF2A\u0134\u0248' },
1467
+ {
1468
+ base: 'K',
1469
+ letters: '\u004B\u24C0\uFF2B\u1E30\u01E8\u1E32\u0136\u1E34\u0198\u2C69\uA740\uA742\uA744\uA7A2',
1470
+ },
1471
+ {
1472
+ base: 'L',
1473
+ letters: '\u004C\u24C1\uFF2C\u013F\u0139\u013D\u1E36\u1E38\u013B\u1E3C\u1E3A\u0141\u023D\u2C62\u2C60\uA748\uA746\uA780',
1474
+ },
1475
+ { base: 'LJ', letters: '\u01C7' },
1476
+ { base: 'Lj', letters: '\u01C8' },
1477
+ { base: 'M', letters: '\u004D\u24C2\uFF2D\u1E3E\u1E40\u1E42\u2C6E\u019C' },
1478
+ {
1479
+ base: 'N',
1480
+ letters: '\u004E\u24C3\uFF2E\u01F8\u0143\u00D1\u1E44\u0147\u1E46\u0145\u1E4A\u1E48\u0220\u019D\uA790\uA7A4',
1481
+ },
1482
+ { base: 'NJ', letters: '\u01CA' },
1483
+ { base: 'Nj', letters: '\u01CB' },
1484
+ {
1485
+ base: 'O',
1486
+ letters: '\u004F\u24C4\uFF2F\u00D2\u00D3\u00D4\u1ED2\u1ED0\u1ED6\u1ED4\u00D5\u1E4C\u022C\u1E4E\u014C\u1E50\u1E52\u014E\u022E\u0230\u00D6\u022A\u1ECE\u0150\u01D1\u020C\u020E\u01A0\u1EDC\u1EDA\u1EE0\u1EDE\u1EE2\u1ECC\u1ED8\u01EA\u01EC\u00D8\u01FE\u0186\u019F\uA74A\uA74C',
1487
+ },
1488
+ { base: 'OI', letters: '\u01A2' },
1489
+ { base: 'OO', letters: '\uA74E' },
1490
+ { base: 'OU', letters: '\u0222' },
1491
+ { base: 'OE', letters: '\u008C\u0152' },
1492
+ { base: 'oe', letters: '\u009C\u0153' },
1493
+ {
1494
+ base: 'P',
1495
+ letters: '\u0050\u24C5\uFF30\u1E54\u1E56\u01A4\u2C63\uA750\uA752\uA754',
1496
+ },
1497
+ { base: 'Q', letters: '\u0051\u24C6\uFF31\uA756\uA758\u024A' },
1498
+ {
1499
+ base: 'R',
1500
+ letters: '\u0052\u24C7\uFF32\u0154\u1E58\u0158\u0210\u0212\u1E5A\u1E5C\u0156\u1E5E\u024C\u2C64\uA75A\uA7A6\uA782',
1501
+ },
1502
+ {
1503
+ base: 'S',
1504
+ letters: '\u0053\u24C8\uFF33\u1E9E\u015A\u1E64\u015C\u1E60\u0160\u1E66\u1E62\u1E68\u0218\u015E\u2C7E\uA7A8\uA784',
1505
+ },
1506
+ {
1507
+ base: 'T',
1508
+ letters: '\u0054\u24C9\uFF34\u1E6A\u0164\u1E6C\u021A\u0162\u1E70\u1E6E\u0166\u01AC\u01AE\u023E\uA786',
1509
+ },
1510
+ { base: 'TZ', letters: '\uA728' },
1511
+ {
1512
+ base: 'U',
1513
+ letters: '\u0055\u24CA\uFF35\u00D9\u00DA\u00DB\u0168\u1E78\u016A\u1E7A\u016C\u00DC\u01DB\u01D7\u01D5\u01D9\u1EE6\u016E\u0170\u01D3\u0214\u0216\u01AF\u1EEA\u1EE8\u1EEE\u1EEC\u1EF0\u1EE4\u1E72\u0172\u1E76\u1E74\u0244',
1514
+ },
1515
+ { base: 'V', letters: '\u0056\u24CB\uFF36\u1E7C\u1E7E\u01B2\uA75E\u0245' },
1516
+ { base: 'VY', letters: '\uA760' },
1517
+ {
1518
+ base: 'W',
1519
+ letters: '\u0057\u24CC\uFF37\u1E80\u1E82\u0174\u1E86\u1E84\u1E88\u2C72',
1520
+ },
1521
+ { base: 'X', letters: '\u0058\u24CD\uFF38\u1E8A\u1E8C' },
1522
+ {
1523
+ base: 'Y',
1524
+ letters: '\u0059\u24CE\uFF39\u1EF2\u00DD\u0176\u1EF8\u0232\u1E8E\u0178\u1EF6\u1EF4\u01B3\u024E\u1EFE',
1525
+ },
1526
+ {
1527
+ base: 'Z',
1528
+ letters: '\u005A\u24CF\uFF3A\u0179\u1E90\u017B\u017D\u1E92\u1E94\u01B5\u0224\u2C7F\u2C6B\uA762',
1529
+ },
1530
+ {
1531
+ base: 'a',
1532
+ letters: '\u0061\u24D0\uFF41\u1E9A\u00E0\u00E1\u00E2\u1EA7\u1EA5\u1EAB\u1EA9\u00E3\u0101\u0103\u1EB1\u1EAF\u1EB5\u1EB3\u0227\u01E1\u00E4\u01DF\u1EA3\u00E5\u01FB\u01CE\u0201\u0203\u1EA1\u1EAD\u1EB7\u1E01\u0105\u2C65\u0250',
1533
+ },
1534
+ { base: 'aa', letters: '\uA733' },
1535
+ { base: 'ae', letters: '\u00E6\u01FD\u01E3' },
1536
+ { base: 'ao', letters: '\uA735' },
1537
+ { base: 'au', letters: '\uA737' },
1538
+ { base: 'av', letters: '\uA739\uA73B' },
1539
+ { base: 'ay', letters: '\uA73D' },
1540
+ {
1541
+ base: 'b',
1542
+ letters: '\u0062\u24D1\uFF42\u1E03\u1E05\u1E07\u0180\u0183\u0253',
1543
+ },
1544
+ {
1545
+ base: 'c',
1546
+ letters: '\u0063\u24D2\uFF43\u0107\u0109\u010B\u010D\u00E7\u1E09\u0188\u023C\uA73F\u2184',
1547
+ },
1548
+ {
1549
+ base: 'd',
1550
+ letters: '\u0064\u24D3\uFF44\u1E0B\u010F\u1E0D\u1E11\u1E13\u1E0F\u0111\u018C\u0256\u0257\uA77A',
1551
+ },
1552
+ { base: 'dz', letters: '\u01F3\u01C6' },
1553
+ {
1554
+ base: 'e',
1555
+ letters: '\u0065\u24D4\uFF45\u00E8\u00E9\u00EA\u1EC1\u1EBF\u1EC5\u1EC3\u1EBD\u0113\u1E15\u1E17\u0115\u0117\u00EB\u1EBB\u011B\u0205\u0207\u1EB9\u1EC7\u0229\u1E1D\u0119\u1E19\u1E1B\u0247\u025B\u01DD',
1556
+ },
1557
+ { base: 'f', letters: '\u0066\u24D5\uFF46\u1E1F\u0192\uA77C' },
1558
+ {
1559
+ base: 'g',
1560
+ letters: '\u0067\u24D6\uFF47\u01F5\u011D\u1E21\u011F\u0121\u01E7\u0123\u01E5\u0260\uA7A1\u1D79\uA77F',
1561
+ },
1562
+ {
1563
+ base: 'h',
1564
+ letters: '\u0068\u24D7\uFF48\u0125\u1E23\u1E27\u021F\u1E25\u1E29\u1E2B\u1E96\u0127\u2C68\u2C76\u0265',
1565
+ },
1566
+ { base: 'hv', letters: '\u0195' },
1567
+ {
1568
+ base: 'i',
1569
+ letters: '\u0069\u24D8\uFF49\u00EC\u00ED\u00EE\u0129\u012B\u012D\u00EF\u1E2F\u1EC9\u01D0\u0209\u020B\u1ECB\u012F\u1E2D\u0268\u0131',
1570
+ },
1571
+ { base: 'j', letters: '\u006A\u24D9\uFF4A\u0135\u01F0\u0249' },
1572
+ {
1573
+ base: 'k',
1574
+ letters: '\u006B\u24DA\uFF4B\u1E31\u01E9\u1E33\u0137\u1E35\u0199\u2C6A\uA741\uA743\uA745\uA7A3',
1575
+ },
1576
+ {
1577
+ base: 'l',
1578
+ letters: '\u006C\u24DB\uFF4C\u0140\u013A\u013E\u1E37\u1E39\u013C\u1E3D\u1E3B\u017F\u0142\u019A\u026B\u2C61\uA749\uA781\uA747',
1579
+ },
1580
+ { base: 'lj', letters: '\u01C9' },
1581
+ { base: 'm', letters: '\u006D\u24DC\uFF4D\u1E3F\u1E41\u1E43\u0271\u026F' },
1582
+ {
1583
+ base: 'n',
1584
+ letters: '\u006E\u24DD\uFF4E\u01F9\u0144\u00F1\u1E45\u0148\u1E47\u0146\u1E4B\u1E49\u019E\u0272\u0149\uA791\uA7A5',
1585
+ },
1586
+ { base: 'nj', letters: '\u01CC' },
1587
+ {
1588
+ base: 'o',
1589
+ letters: '\u006F\u24DE\uFF4F\u00F2\u00F3\u00F4\u1ED3\u1ED1\u1ED7\u1ED5\u00F5\u1E4D\u022D\u1E4F\u014D\u1E51\u1E53\u014F\u022F\u0231\u00F6\u022B\u1ECF\u0151\u01D2\u020D\u020F\u01A1\u1EDD\u1EDB\u1EE1\u1EDF\u1EE3\u1ECD\u1ED9\u01EB\u01ED\u00F8\u01FF\u0254\uA74B\uA74D\u0275',
1590
+ },
1591
+ { base: 'oi', letters: '\u01A3' },
1592
+ { base: 'ou', letters: '\u0223' },
1593
+ { base: 'oo', letters: '\uA74F' },
1594
+ {
1595
+ base: 'p',
1596
+ letters: '\u0070\u24DF\uFF50\u1E55\u1E57\u01A5\u1D7D\uA751\uA753\uA755',
1597
+ },
1598
+ { base: 'q', letters: '\u0071\u24E0\uFF51\u024B\uA757\uA759' },
1599
+ {
1600
+ base: 'r',
1601
+ letters: '\u0072\u24E1\uFF52\u0155\u1E59\u0159\u0211\u0213\u1E5B\u1E5D\u0157\u1E5F\u024D\u027D\uA75B\uA7A7\uA783',
1602
+ },
1603
+ {
1604
+ base: 's',
1605
+ letters: '\u0073\u24E2\uFF53\u00DF\u015B\u1E65\u015D\u1E61\u0161\u1E67\u1E63\u1E69\u0219\u015F\u023F\uA7A9\uA785\u1E9B',
1606
+ },
1607
+ {
1608
+ base: 't',
1609
+ letters: '\u0074\u24E3\uFF54\u1E6B\u1E97\u0165\u1E6D\u021B\u0163\u1E71\u1E6F\u0167\u01AD\u0288\u2C66\uA787',
1610
+ },
1611
+ { base: 'tz', letters: '\uA729' },
1612
+ {
1613
+ base: 'u',
1614
+ letters: '\u0075\u24E4\uFF55\u00F9\u00FA\u00FB\u0169\u1E79\u016B\u1E7B\u016D\u00FC\u01DC\u01D8\u01D6\u01DA\u1EE7\u016F\u0171\u01D4\u0215\u0217\u01B0\u1EEB\u1EE9\u1EEF\u1EED\u1EF1\u1EE5\u1E73\u0173\u1E77\u1E75\u0289',
1615
+ },
1616
+ { base: 'v', letters: '\u0076\u24E5\uFF56\u1E7D\u1E7F\u028B\uA75F\u028C' },
1617
+ { base: 'vy', letters: '\uA761' },
1618
+ {
1619
+ base: 'w',
1620
+ letters: '\u0077\u24E6\uFF57\u1E81\u1E83\u0175\u1E87\u1E85\u1E98\u1E89\u2C73',
1621
+ },
1622
+ { base: 'x', letters: '\u0078\u24E7\uFF58\u1E8B\u1E8D' },
1623
+ {
1624
+ base: 'y',
1625
+ letters: '\u0079\u24E8\uFF59\u1EF3\u00FD\u0177\u1EF9\u0233\u1E8F\u00FF\u1EF7\u1E99\u1EF5\u01B4\u024F\u1EFF',
1626
+ },
1627
+ {
1628
+ base: 'z',
1629
+ letters: '\u007A\u24E9\uFF5A\u017A\u1E91\u017C\u017E\u1E93\u1E95\u01B6\u0225\u0240\u2C6C\uA763',
1630
+ },
1631
+ ];
1632
+ /**
1633
+ * Map of letters from diacritic variant to diacritless variant
1634
+ * Contains lowercase and uppercase separatelly
1635
+ *
1636
+ * > "á" => "a"
1637
+ * > "ě" => "e"
1638
+ * > "Ă" => "A"
1639
+ * > ...
1640
+ *
1641
+ * @public exported from `@promptbook/utils`
1642
+ */
1643
+ var DIACRITIC_VARIANTS_LETTERS = {};
1644
+ // tslint:disable-next-line: prefer-for-of
1645
+ for (var i = 0; i < defaultDiacriticsRemovalMap.length; i++) {
1646
+ var letters = defaultDiacriticsRemovalMap[i].letters;
1647
+ // tslint:disable-next-line: prefer-for-of
1648
+ for (var j = 0; j < letters.length; j++) {
1649
+ DIACRITIC_VARIANTS_LETTERS[letters[j]] = defaultDiacriticsRemovalMap[i].base;
1650
+ }
1651
+ }
1652
+ // <- TODO: [🍓] Put to maker function to save execution time if not needed
1653
+ /*
1654
+ @see https://stackoverflow.com/questions/990904/remove-accents-diacritics-in-a-string-in-javascript
1655
+ Licensed under the Apache License, Version 2.0 (the "License");
1656
+ you may not use this file except in compliance with the License.
1657
+ You may obtain a copy of the License at
1658
+
1659
+ http://www.apache.org/licenses/LICENSE-2.0
1660
+
1661
+ Unless required by applicable law or agreed to in writing, software
1662
+ distributed under the License is distributed on an "AS IS" BASIS,
1663
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1664
+ See the License for the specific language governing permissions and
1665
+ limitations under the License.
1666
+ */
1667
+
1668
+ /**
1669
+ * @@@
1670
+ *
1671
+ * @param input @@@
1672
+ * @returns @@@
1673
+ * @public exported from `@promptbook/utils`
1674
+ */
1675
+ function removeDiacritics(input) {
1676
+ /*eslint no-control-regex: "off"*/
1677
+ return input.replace(/[^\u0000-\u007E]/g, function (a) {
1678
+ return DIACRITIC_VARIANTS_LETTERS[a] || a;
1679
+ });
1680
+ }
1681
+ /**
1682
+ * TODO: [Ж] Variant for cyrillic (and in general non-latin) letters
1683
+ */
1684
+
1685
+ /**
1686
+ * Removes emojis from a string and fix whitespaces
1687
+ *
1688
+ * @param text with emojis
1689
+ * @returns text without emojis
1690
+ * @public exported from `@promptbook/utils`
1691
+ */
1692
+ function removeEmojis(text) {
1693
+ // Replace emojis (and also ZWJ sequence) with hyphens
1694
+ text = text.replace(/(\p{Extended_Pictographic})\p{Modifier_Symbol}/gu, '$1');
1695
+ text = text.replace(/(\p{Extended_Pictographic})[\u{FE00}-\u{FE0F}]/gu, '$1');
1696
+ text = text.replace(/(\p{Extended_Pictographic})(\u{200D}\p{Extended_Pictographic})*/gu, '$1');
1697
+ text = text.replace(/\p{Extended_Pictographic}/gu, '');
1698
+ return text;
1699
+ }
1700
+
1701
+ /**
1702
+ * Removes quotes from a string
1703
+ *
1704
+ * Tip: This is very usefull for post-processing of the result of the LLM model
1705
+ * Note: This function removes only the same quotes from the beginning and the end of the string
1706
+ * Note: There are two simmilar functions:
1707
+ * - `removeQuotes` which removes only bounding quotes
1708
+ * - `unwrapResult` which removes whole introduce sentence
1709
+ *
1710
+ * @param text optionally quoted text
1711
+ * @returns text without quotes
1712
+ * @public exported from `@promptbook/utils`
1713
+ */
1714
+ function removeQuotes(text) {
1715
+ if (text.startsWith('"') && text.endsWith('"')) {
1716
+ return text.slice(1, -1);
1717
+ }
1718
+ if (text.startsWith('\'') && text.endsWith('\'')) {
1719
+ return text.slice(1, -1);
1720
+ }
1721
+ return text;
1722
+ }
1723
+
1724
+ /**
1725
+ * Function `validateParameterName` will @@@
1726
+ *
1727
+ * @param parameterName @@@
1728
+ * @returns @@@
1729
+ * @throws {ParseError} @@@
1730
+ * @private within the repository
1731
+ */
1732
+ function validateParameterName(parameterName) {
1733
+ var e_1, _a;
1734
+ var rawParameterName = parameterName;
1735
+ try {
1736
+ for (var _b = __values([
1737
+ ['`', '`'],
1738
+ ['{', '}'],
1739
+ ['[', ']'],
1740
+ ['(', ')'],
1741
+ ['<', '>'],
1742
+ ]), _c = _b.next(); !_c.done; _c = _b.next()) {
1743
+ var _d = __read(_c.value, 2), start = _d[0], end = _d[1];
1744
+ if (parameterName.substring(0, 1) === start &&
1745
+ parameterName.substring(parameterName.length - 1, parameterName.length) === end
1746
+ // <- TODO: More universal that 1 character
1747
+ ) {
1748
+ parameterName = parameterName.substring(1, parameterName.length - 1);
1749
+ // <- TODO: More universal that 1 character
1750
+ }
1751
+ }
1752
+ }
1753
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
1754
+ finally {
1755
+ try {
1756
+ if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
1757
+ }
1758
+ finally { if (e_1) throw e_1.error; }
1759
+ }
1760
+ // TODO: [🐠] Following try-catch block should be part of common validators logic
1761
+ try {
1762
+ /*
1763
+ Note: We don't need to check for spaces because we are going to normalize the parameter name to camelCase
1764
+ if (parameterName.includes(' ')) {
1765
+ throw new ParseError(`Parameter name cannot contain spaces`);
1766
+ }
1767
+ */
1768
+ if (parameterName.includes('.')) {
1769
+ throw new ParseError("Parameter name cannot contain dots");
1770
+ }
1771
+ if (parameterName.includes('/') || parameterName.includes('\\')) {
1772
+ throw new ParseError("Parameter name cannot contain slashes");
1773
+ }
1774
+ if (parameterName.includes('(') ||
1775
+ parameterName.includes(')') ||
1776
+ parameterName.includes('{') ||
1777
+ parameterName.includes('}') ||
1778
+ parameterName.includes('[') ||
1779
+ parameterName.includes(']')) {
1780
+ throw new ParseError("Parameter name cannot contain braces");
1781
+ }
1782
+ parameterName = removeDiacritics(parameterName);
1783
+ parameterName = removeEmojis(parameterName);
1784
+ parameterName = removeQuotes(parameterName);
1785
+ parameterName = normalizeTo_camelCase(parameterName);
1786
+ if (parameterName === '') {
1787
+ throw new ParseError("Parameter name cannot be empty");
1788
+ }
1789
+ if (RESERVED_PARAMETER_NAMES.includes(parameterName)) {
1790
+ throw new ParseError("{".concat(parameterName, "} is a reserved parameter name"));
1791
+ }
1792
+ }
1793
+ catch (error) {
1794
+ if (!(error instanceof ParseError)) {
1795
+ throw error;
1796
+ }
1797
+ throw new ParseError(spaceTrim__default["default"](function (block) { return "\n ".concat(block(error.message), "\n\n Tried to validate parameter name:\n ").concat(block(rawParameterName), "\n "); }));
1798
+ }
1799
+ return parameterName;
1800
+ }
1801
+
1802
+ /**
1803
+ * Parses the foreach command
1804
+ *
1805
+ * Note: @@@ This command is used as foreach for new commands - it should NOT be used in any `.book.md` file
1806
+ *
1807
+ * @see `documentationUrl` for more details
1808
+ * @public exported from `@promptbook/editable`
1809
+ */
1810
+ var foreachCommandParser = {
1811
+ /**
1812
+ * Name of the command
1813
+ */
1814
+ name: 'FOREACH',
1815
+ /**
1816
+ * Aliases for the FOREACH command
1817
+ */
1818
+ aliasNames: ['FOR', 'EACH'],
1819
+ /**
1820
+ * FOREACH command can be used in:
1821
+ */
1822
+ isUsedInPipelineHead: false,
1823
+ isUsedInPipelineTask: true,
1824
+ /**
1825
+ * Description of the FOREACH command
1826
+ */
1827
+ description: "@@",
1828
+ /**
1829
+ * Link to documentation
1830
+ */
1831
+ documentationUrl: 'https://github.com/webgptorg/promptbook/discussions/148',
1832
+ /**
1833
+ * Example usages of the FOREACH command
1834
+ */
1835
+ examples: [
1836
+ 'FOREACH Text Line `{customers}` -> `{customer}`',
1837
+ 'FOREACH Csv Cell `{customers}` -> `{cell}`',
1838
+ 'FOREACH Csv Row `{customers}` -> `{firstName}`, `{lastName}`, `+{email}`',
1839
+ 'FOR Text Line `{customers}` -> `{customer}`',
1840
+ 'EACH Text Line `{customers}` -> `{customer}`',
1841
+ ],
1842
+ /**
1843
+ * Parses the FOREACH command
1844
+ */
1845
+ parse: function (input) {
1846
+ var args = input.args;
1847
+ var formatName = normalizeTo_SCREAMING_CASE(args[0] || '');
1848
+ var subformatName = normalizeTo_SCREAMING_CASE(args[1] || '');
1849
+ var parameterNameArg = args[2] || '';
1850
+ var assignSign = args[3];
1851
+ var formatDefinition = FORMAT_DEFINITIONS.find(function (formatDefinition) {
1852
+ return __spreadArray([formatDefinition.formatName], __read((formatDefinition.aliases || [])), false).includes(formatName);
1853
+ });
1854
+ if (formatDefinition === undefined) {
1855
+ throw new ParseError(spaceTrim__default["default"](function (block) { return "\n Unsupported format \"".concat(formatName, "\"\n\n Available formats:\n ").concat(block(FORMAT_DEFINITIONS.map(function (formatDefinition) { return formatDefinition.formatName; })
1856
+ .map(function (formatName) { return "- ".concat(formatName); })
1857
+ .join('\n')), "\n "); }));
1858
+ // <- TODO: [🏢] List all supported format names
1859
+ }
1860
+ var subvalueDefinition = formatDefinition.subvalueDefinitions.find(function (subvalueDefinition) {
1861
+ return __spreadArray([subvalueDefinition.subvalueName], __read((subvalueDefinition.aliases || [])), false).includes(subformatName);
1862
+ });
1863
+ if (subvalueDefinition === undefined) {
1864
+ throw new ParseError(spaceTrim__default["default"](function (block) { return "\n Unsupported subformat name \"".concat(subformatName, "\" for format \"").concat(formatName, "\"\n\n Available subformat names for format \"").concat(formatDefinition.formatName, "\":\n ").concat(block(formatDefinition.subvalueDefinitions
1865
+ .map(function (subvalueDefinition) { return subvalueDefinition.subvalueName; })
1866
+ .map(function (subvalueName) { return "- ".concat(subvalueName); })
1867
+ .join('\n')), "\n "); }));
1868
+ // <- TODO: [🏢] List all supported subformat names for the format
1869
+ }
1870
+ if (assignSign !== '->') {
1871
+ throw new ParseError("FOREACH command must have '->' to assign the value to the parameter");
1872
+ }
1873
+ var parameterName = validateParameterName(parameterNameArg);
1874
+ var outputSubparameterName = null;
1875
+ // TODO: [4] DRY
1876
+ var inputSubparameterNames = args
1877
+ .slice(4)
1878
+ .map(function (parameterName) { return parameterName.split(',').join(' ').trim(); })
1879
+ .filter(function (parameterName) { return !parameterName.includes('+'); })
1880
+ .filter(function (parameterName) { return parameterName !== ''; })
1881
+ .map(validateParameterName);
1882
+ // TODO: [4] DRY
1883
+ var outputSubparameterNames = args
1884
+ .slice(4)
1885
+ .map(function (parameterName) { return parameterName.split(',').join(' ').trim(); })
1886
+ .filter(function (parameterName) { return parameterName.includes('+'); })
1887
+ .map(function (parameterName) { return parameterName.split('+').join(''); })
1888
+ .map(validateParameterName);
1889
+ if (outputSubparameterNames.length === 1) {
1890
+ outputSubparameterName = outputSubparameterNames[0];
1891
+ }
1892
+ else if (outputSubparameterNames.length > 1) {
1893
+ throw new ParseError("FOREACH command can not have more than one output subparameter");
1894
+ }
1895
+ if (inputSubparameterNames.length === 0) {
1896
+ throw new ParseError("FOREACH command must have at least one input subparameter");
1897
+ }
1898
+ if (outputSubparameterName === null) {
1899
+ // TODO: Following code should be unhardcoded from here and moved to the format definition
1900
+ if (formatName === 'CSV' && subformatName === 'CELL') {
1901
+ outputSubparameterName = 'newCell';
1902
+ }
1903
+ else if (formatName === 'TEXT' && subformatName === 'LINE') {
1904
+ outputSubparameterName = 'newLine';
1905
+ }
1906
+ else {
1907
+ throw new ParseError(spaceTrim__default["default"]("\n FOREACH ".concat(formatName, " ").concat(subformatName, " must specify output subparameter\n\n Correct example:\n - FOREACH ").concat(formatName, " ").concat(subformatName, " {").concat(parameterName, "} -> {inputSubparameterName1}, {inputSubparameterName2}, +{outputSubparameterName}\n\n ")));
1908
+ }
1909
+ }
1910
+ return {
1911
+ type: 'FOREACH',
1912
+ formatName: formatName,
1913
+ subformatName: subformatName,
1914
+ parameterName: parameterName,
1915
+ inputSubparameterNames: inputSubparameterNames,
1916
+ outputSubparameterName: outputSubparameterName,
1917
+ };
1918
+ },
1919
+ /**
1920
+ * Apply the FOREACH command to the `pipelineJson`
1921
+ *
1922
+ * Note: `$` is used to indicate that this function mutates given `taskJson`
1923
+ */
1924
+ $applyToTaskJson: function (command, $taskJson, $pipelineJson) {
1925
+ var formatName = command.formatName, subformatName = command.subformatName, parameterName = command.parameterName, inputSubparameterNames = command.inputSubparameterNames, outputSubparameterName = command.outputSubparameterName;
1926
+ // TODO: [🍭] Detect double use
1927
+ // TODO: [🍭] Detect usage with JOKER and don't allow it
1928
+ $taskJson.foreach = {
1929
+ formatName: formatName,
1930
+ subformatName: subformatName,
1931
+ parameterName: parameterName,
1932
+ inputSubparameterNames: inputSubparameterNames,
1933
+ outputSubparameterName: outputSubparameterName,
1934
+ };
1935
+ // Note: [🍭] FOREACH apply has some sideeffects on different places in codebase
1936
+ },
1937
+ /**
1938
+ * Converts the FOREACH command back to string
1939
+ *
1940
+ * Note: This is used in `pipelineJsonToString` utility
1941
+ */
1942
+ stringify: function (command) {
1943
+ return "---"; // <- TODO: [🛋] Implement
1944
+ },
1945
+ /**
1946
+ * Reads the FOREACH command from the `TaskJson`
1947
+ *
1948
+ * Note: This is used in `pipelineJsonToString` utility
1949
+ */
1950
+ takeFromTaskJson: function ($taskJson) {
1951
+ throw new NotYetImplementedError("[\uD83D\uDECB] Not implemented yet"); // <- TODO: [🛋] Implement
1952
+ },
1953
+ };
1954
+ /**
1955
+ * TODO: [🍭] Make .book.md file with examples of the FOREACH with wrong parsing and logic
1956
+ */
1957
+
1958
+ /**
1959
+ * Parses the format command
1960
+ *
1961
+ * @see `documentationUrl` for more details
1962
+ * @public exported from `@promptbook/editable`
1963
+ */
1964
+ var formatCommandParser = {
1965
+ /**
1966
+ * Name of the command
1967
+ */
1968
+ name: 'FORMAT',
1969
+ /**
1970
+ * BOILERPLATE command can be used in:
1971
+ */
1972
+ isUsedInPipelineHead: false,
1973
+ isUsedInPipelineTask: true,
1974
+ /**
1975
+ * Description of the FORMAT command
1976
+ */
1977
+ description: spaceTrim__default["default"]("\n Format command describes the desired output of the task (after post-processing)\n It can set limits for the maximum/minimum length of the output, measured in characters, words, sentences, paragraphs or some other shape of the output.\n "),
1978
+ /**
1979
+ * Link to documentation
1980
+ */
1981
+ documentationUrl: 'https://github.com/webgptorg/promptbook/discussions/30',
1982
+ /**
1983
+ * Example usages of the FORMAT command
1984
+ */
1985
+ examples: ['FORMAT JSON'],
1986
+ /**
1987
+ * Parses the FORMAT command
1988
+ */
1989
+ parse: function (input) {
1990
+ var normalized = input.normalized;
1991
+ if (!normalized.startsWith('FORMAT_JSON')) {
1992
+ throw new ParseError("For now only JSON format is supported, in future we will support more formats");
1993
+ }
1994
+ return {
1995
+ type: 'FORMAT',
1996
+ format: 'JSON',
1997
+ };
1998
+ // <- TODO: [🦽] Why this is constantly removed by repair-imports.ts
1999
+ // [🥤]
2000
+ },
2001
+ /**
2002
+ * Apply the FORMAT command to the `pipelineJson`
2003
+ *
2004
+ * Note: `$` is used to indicate that this function mutates given `taskJson`
2005
+ */
2006
+ $applyToTaskJson: function (command, $taskJson) {
2007
+ if ($taskJson.format !== undefined && command.format !== $taskJson.format) {
2008
+ throw new ParseError("Format format is already defined to \"".concat($taskJson.format, "\".\n Now you try to redefine it by \"").concat(command.format, "\""));
2009
+ }
2010
+ $taskJson.format = command.format;
2011
+ },
2012
+ /**
2013
+ * Converts the FORMAT command back to string
2014
+ *
2015
+ * Note: This is used in `pipelineJsonToString` utility
2016
+ */
2017
+ stringify: function (command) {
2018
+ return "---"; // <- TODO: [🛋] Implement
2019
+ },
2020
+ /**
2021
+ * Reads the FORMAT command from the `TaskJson`
2022
+ *
2023
+ * Note: This is used in `pipelineJsonToString` utility
2024
+ */
2025
+ takeFromTaskJson: function ($taskJson) {
2026
+ throw new NotYetImplementedError("[\uD83D\uDECB] Not implemented yet"); // <- TODO: [🛋] Implement
2027
+ },
2028
+ };
2029
+
2030
+ /**
2031
+ * @@@
2032
+ *
2033
+ * @public exported from `@promptbook/core`
2034
+ */
2035
+ var ChatbotFormfactorDefinition = {
2036
+ name: 'CHATBOT',
2037
+ aliasNames: ['CHAT'],
2038
+ description: "@@@",
2039
+ documentationUrl: "https://github.com/webgptorg/promptbook/discussions/174",
2040
+ pipelineInterface: {
2041
+ inputParameters: [
2042
+ {
2043
+ name: 'previousTitle',
2044
+ description: "Previous title of the conversation",
2045
+ isInput: true,
2046
+ isOutput: false,
2047
+ },
2048
+ {
2049
+ name: 'previousConversationSummary',
2050
+ description: "Previous conversation summary",
2051
+ isInput: true,
2052
+ isOutput: false,
2053
+ },
2054
+ { name: 'userMessage', description: "User message", isInput: true, isOutput: false },
2055
+ ],
2056
+ outputParameters: [
2057
+ { name: 'title', description: "Title of the conversation", isInput: false, isOutput: true },
2058
+ { name: 'conversationSummary', description: "Summary of the conversation", isInput: false, isOutput: true },
2059
+ { name: 'chatbotResponse', description: "Chatbot response", isInput: false, isOutput: true },
2060
+ ],
2061
+ },
2062
+ };
2063
+
2064
+ /**
2065
+ * Generator is form of app that @@@
2066
+ *
2067
+ * @public exported from `@promptbook/core`
2068
+ */
2069
+ var GeneratorFormfactorDefinition = {
2070
+ name: 'GENERATOR',
2071
+ description: "Generates any kind (in HTML with possible scripts and css format) of content from input message",
2072
+ documentationUrl: "https://github.com/webgptorg/promptbook/discussions/184",
2073
+ pipelineInterface: {
2074
+ inputParameters: [
2075
+ {
2076
+ name: 'inputMessage',
2077
+ description: "Input message to be image made from",
2078
+ isInput: true,
2079
+ isOutput: false,
2080
+ },
2081
+ ],
2082
+ outputParameters: [
2083
+ {
2084
+ name: 'result',
2085
+ description: "Result in HTML to be shown to user",
2086
+ isInput: false,
2087
+ isOutput: true,
2088
+ },
2089
+ ],
2090
+ },
2091
+ };
2092
+
2093
+ /**
2094
+ * @@@
2095
+ *
2096
+ * @see https://github.com/webgptorg/promptbook/discussions/171
2097
+ *
2098
+ * @public exported from `@promptbook/core`
2099
+ */
2100
+ var GENERIC_PIPELINE_INTERFACE = {
2101
+ inputParameters: [],
2102
+ outputParameters: [],
2103
+ };
2104
+ /**
2105
+ * Note: [💞] Ignore a discrepancy between file name and entity name
2106
+ */
2107
+
2108
+ /**
2109
+ * @@@
2110
+ *
2111
+ * @public exported from `@promptbook/core`
2112
+ */
2113
+ var GenericFormfactorDefinition = {
2114
+ name: 'GENERIC',
2115
+ description: "@@@",
2116
+ documentationUrl: "https://github.com/webgptorg/promptbook/discussions/173",
2117
+ pipelineInterface: GENERIC_PIPELINE_INTERFACE,
2118
+ };
2119
+
2120
+ /**
2121
+ * Image generator is form of app that generates image from input message
2122
+ *
2123
+ * @public exported from `@promptbook/core`
2124
+ */
2125
+ var ImageGeneratorFormfactorDefinition = {
2126
+ name: 'IMAGE_GENERATOR',
2127
+ description: "Generates prompt for image generation from input message",
2128
+ documentationUrl: "https://github.com/webgptorg/promptbook/discussions/184",
2129
+ pipelineInterface: {
2130
+ inputParameters: [
2131
+ {
2132
+ name: 'inputMessage',
2133
+ description: "Input message to be image made from",
2134
+ isInput: true,
2135
+ isOutput: false,
2136
+ },
2137
+ ],
2138
+ outputParameters: [
2139
+ {
2140
+ name: 'prompt',
2141
+ description: "Prompt to be used for image generation",
2142
+ isInput: false,
2143
+ isOutput: true,
2144
+ },
2145
+ ],
2146
+ },
2147
+ };
2148
+
2149
+ /**
2150
+ * Matcher is form of app that @@@
2151
+ *
2152
+ * @public exported from `@promptbook/core`
2153
+ */
2154
+ var MatcherFormfactorDefinition = {
2155
+ name: 'EXPERIMENTAL_MATCHER',
2156
+ description: "@@@",
2157
+ documentationUrl: "https://github.com/webgptorg/promptbook/discussions/177",
2158
+ pipelineInterface: {
2159
+ inputParameters: [
2160
+ /* @@@ */
2161
+ {
2162
+ name: 'nonce',
2163
+ description: 'Just to prevent EXPERIMENTAL_MATCHER to be set as implicit formfactor',
2164
+ isInput: true,
2165
+ isOutput: false,
2166
+ },
2167
+ ],
2168
+ outputParameters: [
2169
+ /* @@@ */
2170
+ ],
2171
+ },
2172
+ };
2173
+
2174
+ /**
2175
+ * Sheets is form of app that @@@
2176
+ *
2177
+ * @public exported from `@promptbook/core`
2178
+ */
2179
+ var SheetsFormfactorDefinition = {
2180
+ name: 'SHEETS',
2181
+ aliasNames: ['SHEETS', 'SHEET'],
2182
+ description: "@@@",
2183
+ documentationUrl: "https://github.com/webgptorg/promptbook/discussions/176",
2184
+ pipelineInterface: {
2185
+ inputParameters: [
2186
+ {
2187
+ name: 'inputSheet',
2188
+ description: "Input sheet to be processed as csv",
2189
+ isInput: true,
2190
+ isOutput: false,
2191
+ },
2192
+ ],
2193
+ outputParameters: [
2194
+ {
2195
+ name: 'outputSheet',
2196
+ description: "Output sheet as csv",
2197
+ isInput: false,
2198
+ isOutput: true,
2199
+ },
2200
+ ],
2201
+ },
2202
+ };
2203
+
2204
+ /**
2205
+ * Translator is form of app that @@@
2206
+ *
2207
+ * @public exported from `@promptbook/core`
2208
+ */
2209
+ var TranslatorFormfactorDefinition = {
2210
+ name: 'TRANSLATOR',
2211
+ description: "@@@",
2212
+ documentationUrl: "https://github.com/webgptorg/promptbook/discussions/175",
2213
+ pipelineInterface: {
2214
+ inputParameters: [
2215
+ {
2216
+ name: 'inputMessage',
2217
+ description: "Input message to be translated",
2218
+ isInput: true,
2219
+ isOutput: false,
2220
+ },
2221
+ ],
2222
+ outputParameters: [
2223
+ {
2224
+ name: 'outputMessage',
2225
+ description: "Translated output message",
2226
+ isInput: false,
2227
+ isOutput: true,
2228
+ },
2229
+ ],
2230
+ // <- TODO: [🤓] Maybe add {summary}
2231
+ // <- TODO: [🧠] maybe change to {inputText}, {inputText} / or make system for any name of first input and first outpur parameter
2232
+ },
2233
+ };
2234
+
2235
+ /**
2236
+ * All available formfactor definitions
2237
+ *
2238
+ * @public exported from `@promptbook/core`
2239
+ */
2240
+ var FORMFACTOR_DEFINITIONS = [
2241
+ GenericFormfactorDefinition,
2242
+ ChatbotFormfactorDefinition,
2243
+ TranslatorFormfactorDefinition,
2244
+ SheetsFormfactorDefinition,
2245
+ MatcherFormfactorDefinition,
2246
+ GeneratorFormfactorDefinition,
2247
+ ImageGeneratorFormfactorDefinition,
2248
+ ];
2249
+ /**
2250
+ * Note: [💞] Ignore a discrepancy between file name and entity name
2251
+ */
2252
+
2253
+ /**
2254
+ * Parses the formfactor command
2255
+ *
2256
+ * Note: @@@ This command is used as formfactor for new commands - it should NOT be used in any `.book.md` file
2257
+ *
2258
+ * @see `documentationUrl` for more details
2259
+ * @public exported from `@promptbook/editable`
2260
+ */
2261
+ var formfactorCommandParser = {
2262
+ /**
2263
+ * Name of the command
2264
+ */
2265
+ name: 'FORMFACTOR',
2266
+ /**
2267
+ * Aliases for the FORMFACTOR command
2268
+ */
2269
+ aliasNames: ['FORM', 'FF'],
2270
+ /**
2271
+ * FORMFACTOR command can be used in:
2272
+ */
2273
+ isUsedInPipelineHead: true,
2274
+ isUsedInPipelineTask: false,
2275
+ /**
2276
+ * Description of the FORMFACTOR command
2277
+ */
2278
+ description: "@@",
2279
+ /**
2280
+ * Link to documentation
2281
+ */
2282
+ documentationUrl: 'https://github.com/webgptorg/promptbook/discussions/168',
2283
+ /**
2284
+ * Example usages of the FORMFACTOR command
2285
+ */
2286
+ examples: ['FORMFACTOR Chatbot', 'FF Chat'],
2287
+ /**
2288
+ * Parses the FORMFACTOR command
2289
+ */
2290
+ parse: function (input) {
2291
+ var args = input.args;
2292
+ if (args.length !== 1) {
2293
+ throw new ParseError("FORMFACTOR command requires exactly one argument");
2294
+ }
2295
+ var formfactorNameCandidate = args[0].toUpperCase();
2296
+ var formfactor = FORMFACTOR_DEFINITIONS.find(function (definition) {
2297
+ return __spreadArray([definition.name], __read(__assign({ aliasNames: [] }, definition).aliasNames), false).includes(formfactorNameCandidate);
2298
+ });
2299
+ if (formfactor === undefined) {
2300
+ throw new ParseError(spaceTrim__default["default"](function (block) { return "\n Unknown formfactor name \"".concat(formfactorNameCandidate, "\"\n\n Available formfactors:\n ").concat(block(FORMFACTOR_DEFINITIONS.map(function (_a) {
2301
+ var name = _a.name;
2302
+ return "- ".concat(name);
2303
+ }).join('\n')), "\n "); }));
2304
+ }
2305
+ return {
2306
+ type: 'FORMFACTOR',
2307
+ formfactorName: formfactor.name,
2308
+ };
2309
+ },
2310
+ /**
2311
+ * Apply the FORMFACTOR command to the `pipelineJson`
2312
+ *
2313
+ * Note: `$` is used to indicate that this function mutates given `pipelineJson`
2314
+ */
2315
+ $applyToPipelineJson: function (command, $pipelineJson) {
2316
+ if ($pipelineJson.formfactorName !== undefined && $pipelineJson.formfactorName !== command.formfactorName) {
2317
+ throw new ParseError(spaceTrim__default["default"]("\n Redefinition of `FORMFACTOR` in the pipeline head\n\n You have used:\n 1) FORMFACTOR `".concat($pipelineJson.formfactorName, "`\n 2) FORMFACTOR `").concat(command.formfactorName, "`\n ")));
2318
+ }
2319
+ $pipelineJson.formfactorName = command.formfactorName;
2320
+ },
2321
+ /**
2322
+ * Converts the FORMFACTOR command back to string
2323
+ *
2324
+ * Note: This is used in `pipelineJsonToString` utility
2325
+ */
2326
+ stringify: function (command) {
2327
+ return "FORMFACTOR ".concat(command.formfactorName);
2328
+ },
2329
+ /**
2330
+ * Reads the FORMFACTOR command from the `PipelineJson`
2331
+ *
2332
+ * Note: This is used in `pipelineJsonToString` utility
2333
+ */
2334
+ takeFromPipelineJson: function (pipelineJson) {
2335
+ return [
2336
+ {
2337
+ type: 'FORMFACTOR',
2338
+ formfactorName: pipelineJson.formfactorName,
2339
+ },
2340
+ ];
2341
+ },
2342
+ };
2343
+
2344
+ /**
2345
+ * Parses the joker command
2346
+ *
2347
+ * @see `documentationUrl` for more details
2348
+ * @public exported from `@promptbook/editable`
2349
+ */
2350
+ var jokerCommandParser = {
2351
+ /**
2352
+ * Name of the command
2353
+ */
2354
+ name: 'JOKER',
2355
+ /**
2356
+ * BOILERPLATE command can be used in:
2357
+ */
2358
+ isUsedInPipelineHead: false,
2359
+ isUsedInPipelineTask: true,
2360
+ /**
2361
+ * Description of the JOKER command
2362
+ */
2363
+ description: "Joker parameter is used instead of executing the task result if jokers value meets the expectations requirements",
2364
+ /**
2365
+ * Link to documentation
2366
+ */
2367
+ documentationUrl: 'https://github.com/webgptorg/promptbook/discussions/66',
2368
+ /**
2369
+ * Example usages of the JOKER command
2370
+ */
2371
+ examples: ['JOKER {documentTitle}'],
2372
+ /**
2373
+ * Parses the JOKER command
2374
+ */
2375
+ parse: function (input) {
2376
+ var args = input.args;
2377
+ if (args.length !== 1) {
2378
+ throw new ParseError("JOKE command expects exactly one parameter name");
2379
+ }
2380
+ var parameterNameArg = args[0] || '';
2381
+ var parameterName = validateParameterName(parameterNameArg);
2382
+ return {
2383
+ type: 'JOKER',
2384
+ parameterName: parameterName,
2385
+ };
2386
+ },
2387
+ /**
2388
+ * Apply the JOKER command to the `pipelineJson`
2389
+ *
2390
+ * Note: `$` is used to indicate that this function mutates given `taskJson`
2391
+ */
2392
+ $applyToTaskJson: function (command, $taskJson) {
2393
+ $taskJson.jokerParameterNames = $taskJson.jokerParameterNames || [];
2394
+ $taskJson.jokerParameterNames.push(command.parameterName);
2395
+ },
2396
+ /**
2397
+ * Converts the JOKER command back to string
2398
+ *
2399
+ * Note: This is used in `pipelineJsonToString` utility
2400
+ */
2401
+ stringify: function (command) {
2402
+ return "---"; // <- TODO: [🛋] Implement
2403
+ },
2404
+ /**
2405
+ * Reads the JOKER command from the `TaskJson`
2406
+ *
2407
+ * Note: This is used in `pipelineJsonToString` utility
2408
+ */
2409
+ takeFromTaskJson: function ($taskJson) {
2410
+ throw new NotYetImplementedError("[\uD83D\uDECB] Not implemented yet"); // <- TODO: [🛋] Implement
2411
+ },
2412
+ };
2413
+
2414
+ /**
2415
+ * Tests if given string is valid URL.
2416
+ *
2417
+ * Note: This does not check if the file exists only if the path is valid
2418
+ * @public exported from `@promptbook/utils`
2419
+ */
2420
+ function isValidFilePath(filename) {
2421
+ if (typeof filename !== 'string') {
2422
+ return false;
2423
+ }
2424
+ if (filename.split('\n').length > 1) {
2425
+ return false;
2426
+ }
2427
+ if (filename.split(' ').length >
2428
+ 5 /* <- TODO: [🧠][🈷] Make some better non-arbitrary way how to distinct filenames from informational texts */) {
2429
+ return false;
2430
+ }
2431
+ var filenameSlashes = filename.split('\\').join('/');
2432
+ // Absolute Unix path: /hello.txt
2433
+ if (/^(\/)/i.test(filenameSlashes)) {
2434
+ // console.log(filename, 'Absolute Unix path: /hello.txt');
2435
+ return true;
2436
+ }
2437
+ // Absolute Windows path: /hello.txt
2438
+ if (/^([A-Z]{1,2}:\/?)\//i.test(filenameSlashes)) {
2439
+ // console.log(filename, 'Absolute Windows path: /hello.txt');
2440
+ return true;
2441
+ }
2442
+ // Relative path: ./hello.txt
2443
+ if (/^(\.\.?\/)+/i.test(filenameSlashes)) {
2444
+ // console.log(filename, 'Relative path: ./hello.txt');
2445
+ return true;
2446
+ }
2447
+ // Allow paths like foo/hello
2448
+ if (/^[^/]+\/[^/]+/i.test(filenameSlashes)) {
2449
+ // console.log(filename, 'Allow paths like foo/hello');
2450
+ return true;
2451
+ }
2452
+ // Allow paths like hello.book
2453
+ if (/^[^/]+\.[^/]+$/i.test(filenameSlashes)) {
2454
+ // console.log(filename, 'Allow paths like hello.book');
2455
+ return true;
2456
+ }
2457
+ return false;
2458
+ }
2459
+ /**
2460
+ * TODO: [🍏] Implement for MacOs
2461
+ */
2462
+
2463
+ /**
2464
+ * Tests if given string is valid URL.
2465
+ *
2466
+ * Note: Dataurl are considered perfectly valid.
2467
+ * Note: There are two simmilar functions:
2468
+ * - `isValidUrl` which tests any URL
2469
+ * - `isValidPipelineUrl` *(this one)* which tests just promptbook URL
2470
+ *
2471
+ * @public exported from `@promptbook/utils`
2472
+ */
2473
+ function isValidUrl(url) {
2474
+ if (typeof url !== 'string') {
2475
+ return false;
2476
+ }
2477
+ try {
2478
+ if (url.startsWith('blob:')) {
2479
+ url = url.replace(/^blob:/, '');
2480
+ }
2481
+ var urlObject = new URL(url /* because fail is handled */);
2482
+ if (!['http:', 'https:', 'data:'].includes(urlObject.protocol)) {
2483
+ return false;
2484
+ }
2485
+ return true;
2486
+ }
2487
+ catch (error) {
2488
+ return false;
2489
+ }
2490
+ }
2491
+
2492
+ /**
2493
+ * @@@
2494
+ *
2495
+ * @param text @@@
2496
+ * @returns @@@
2497
+ * @example 'hello-world'
2498
+ * @example 'i-love-promptbook'
2499
+ * @public exported from `@promptbook/utils`
2500
+ */
2501
+ function normalizeToKebabCase(text) {
2502
+ var e_1, _a;
2503
+ text = removeDiacritics(text);
2504
+ var charType;
2505
+ var lastCharType = 'OTHER';
2506
+ var normalizedName = '';
2507
+ try {
2508
+ for (var text_1 = __values(text), text_1_1 = text_1.next(); !text_1_1.done; text_1_1 = text_1.next()) {
2509
+ var char = text_1_1.value;
2510
+ var normalizedChar = void 0;
2511
+ if (/^[a-z]$/.test(char)) {
2512
+ charType = 'LOWERCASE';
2513
+ normalizedChar = char;
2514
+ }
2515
+ else if (/^[A-Z]$/.test(char)) {
2516
+ charType = 'UPPERCASE';
2517
+ normalizedChar = char.toLowerCase();
2518
+ }
2519
+ else if (/^[0-9]$/.test(char)) {
2520
+ charType = 'NUMBER';
2521
+ normalizedChar = char;
2522
+ }
2523
+ else {
2524
+ charType = 'OTHER';
2525
+ normalizedChar = '-';
2526
+ }
2527
+ if (charType !== lastCharType &&
2528
+ !(lastCharType === 'UPPERCASE' && charType === 'LOWERCASE') &&
2529
+ !(lastCharType === 'NUMBER') &&
2530
+ !(charType === 'NUMBER')) {
2531
+ normalizedName += '-';
2532
+ }
2533
+ normalizedName += normalizedChar;
2534
+ lastCharType = charType;
2535
+ }
2536
+ }
2537
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
2538
+ finally {
2539
+ try {
2540
+ if (text_1_1 && !text_1_1.done && (_a = text_1.return)) _a.call(text_1);
2541
+ }
2542
+ finally { if (e_1) throw e_1.error; }
2543
+ }
2544
+ normalizedName = normalizedName.split(/-+/g).join('-');
2545
+ normalizedName = normalizedName.split(/-?\/-?/g).join('/');
2546
+ normalizedName = normalizedName.replace(/^-/, '');
2547
+ normalizedName = normalizedName.replace(/-$/, '');
2548
+ return normalizedName;
2549
+ }
2550
+ /**
2551
+ * Note: [💞] Ignore a discrepancy between file name and entity name
2552
+ */
2553
+
2554
+ /**
2555
+ * Creates unique name for the source
2556
+ *
2557
+ * @public exported from `@promptbook/editable`
2558
+ */
2559
+ function knowledgeSourceContentToName(knowledgeSourceContent) {
2560
+ var hash = cryptoJs.SHA256(hexEncoder__default["default"].parse(JSON.stringify(knowledgeSourceContent)))
2561
+ // <- TODO: [🥬] Encapsulate sha256 to some private utility function
2562
+ .toString( /* hex */)
2563
+ .substring(0, 20);
2564
+ // <- TODO: [🥬] Make some system for hashes and ids of promptbook
2565
+ var semanticName = normalizeToKebabCase(knowledgeSourceContent.substring(0, 20));
2566
+ var pieces = ['source', semanticName, hash].filter(function (piece) { return piece !== ''; });
2567
+ var name = pieces.join('-').split('--').join('-');
2568
+ // <- TODO: Use MAX_FILENAME_LENGTH
2569
+ return name;
2570
+ }
2571
+ /**
2572
+ * TODO: [🐱‍🐉][🧠] Make some smart crop NOT source-i-m-pavol-a-develop-... BUT source-i-m-pavol-a-developer-...
2573
+ */
2574
+
2575
+ /**
2576
+ * Parses the knowledge command
2577
+ *
2578
+ * @see `documentationUrl` for more details
2579
+ * @public exported from `@promptbook/editable`
2580
+ */
2581
+ var knowledgeCommandParser = {
2582
+ /**
2583
+ * Name of the command
2584
+ */
2585
+ name: 'KNOWLEDGE',
2586
+ /**
2587
+ * BOILERPLATE command can be used in:
2588
+ */
2589
+ isUsedInPipelineHead: true,
2590
+ isUsedInPipelineTask: false,
2591
+ /**
2592
+ * Description of the KNOWLEDGE command
2593
+ */
2594
+ description: "Tells promptbook which external knowledge to use",
2595
+ /**
2596
+ * Link to documentation
2597
+ */
2598
+ documentationUrl: 'https://github.com/webgptorg/promptbook/discussions/41',
2599
+ /**
2600
+ * Example usages of the KNOWLEDGE command
2601
+ */
2602
+ examples: [
2603
+ 'KNOWLEDGE https://www.pavolhejny.com/',
2604
+ 'KNOWLEDGE ./hejny-cv.txt',
2605
+ 'KNOWLEDGE ./hejny-cv.md',
2606
+ 'KNOWLEDGE ./hejny-cv.pdf',
2607
+ 'KNOWLEDGE ./hejny-cv.docx',
2608
+ // <- TODO: [😿] Allow ONLY files scoped in the (sub)directory NOT ../ and test it
2609
+ ],
2610
+ /**
2611
+ * Parses the KNOWLEDGE command
2612
+ */
2613
+ parse: function (input) {
2614
+ var args = input.args;
2615
+ var knowledgeSourceContent = spaceTrim__default["default"](args[0] || '');
2616
+ if (knowledgeSourceContent === '') {
2617
+ throw new ParseError("Source is not defined");
2618
+ }
2619
+ // TODO: [main] !!4 Following checks should be applied every link in the `sourceContent`
2620
+ if (knowledgeSourceContent.startsWith('http://')) {
2621
+ throw new ParseError("Source is not secure");
2622
+ }
2623
+ if (!(isValidFilePath(knowledgeSourceContent) || isValidUrl(knowledgeSourceContent))) {
2624
+ throw new ParseError("Source not valid");
2625
+ }
2626
+ if (knowledgeSourceContent.startsWith('../') ||
2627
+ knowledgeSourceContent.startsWith('/') ||
2628
+ /^[A-Z]:[\\/]+/i.test(knowledgeSourceContent)) {
2629
+ throw new ParseError("Source cannot be outside of the .book.md folder");
2630
+ }
2631
+ return {
2632
+ type: 'KNOWLEDGE',
2633
+ knowledgeSourceContent: knowledgeSourceContent,
2634
+ };
2635
+ },
2636
+ /**
2637
+ * Apply the KNOWLEDGE command to the `pipelineJson`
2638
+ *
2639
+ * Note: `$` is used to indicate that this function mutates given `pipelineJson`
2640
+ */
2641
+ $applyToPipelineJson: function (command, $pipelineJson) {
2642
+ var knowledgeSourceContent = command.knowledgeSourceContent;
2643
+ $pipelineJson.knowledgeSources.push({
2644
+ name: knowledgeSourceContentToName(knowledgeSourceContent),
2645
+ knowledgeSourceContent: knowledgeSourceContent,
2646
+ });
2647
+ },
2648
+ /**
2649
+ * Converts the KNOWLEDGE command back to string
2650
+ *
2651
+ * Note: This is used in `pipelineJsonToString` utility
2652
+ */
2653
+ stringify: function (command) {
2654
+ return "---"; // <- TODO: [🛋] Implement
2655
+ },
2656
+ /**
2657
+ * Reads the KNOWLEDGE command from the `PipelineJson`
2658
+ *
2659
+ * Note: This is used in `pipelineJsonToString` utility
2660
+ */
2661
+ takeFromPipelineJson: function (pipelineJson) {
2662
+ throw new NotYetImplementedError("[\uD83D\uDECB] Not implemented yet"); // <- TODO: [🛋] Implement
2663
+ },
2664
+ };
2665
+ /**
2666
+ * Note: [⛱] There are two types of KNOWLEDGE commands *...(read more in [⛱])*
2667
+ */
2668
+
2669
+ /**
2670
+ * @@@
2671
+ *
2672
+ * @public exported from `@promptbook/core`
2673
+ */
2674
+ var MODEL_VARIANTS = ['COMPLETION', 'CHAT', 'EMBEDDING' /* <- TODO [🏳] */ /* <- [🤖] */];
2675
+
2676
+ /**
2677
+ * Parses the model command
2678
+ *
2679
+ * @see `documentationUrl` for more details
2680
+ * @deprecated Option to manually set the model requirements is not recommended to use, use `PERSONA` instead
2681
+ * @public exported from `@promptbook/editable`
2682
+ */
2683
+ var modelCommandParser = {
2684
+ /**
2685
+ * Name of the command
2686
+ */
2687
+ name: 'MODEL',
2688
+ /**
2689
+ * BOILERPLATE command can be used in:
2690
+ */
2691
+ isUsedInPipelineHead: true,
2692
+ isUsedInPipelineTask: true,
2693
+ /**
2694
+ * Description of the MODEL command
2695
+ */
2696
+ description: "Tells which `modelRequirements` (for example which model) to use for the prompt task execution",
2697
+ /**
2698
+ * Link to documentation
2699
+ */
2700
+ documentationUrl: 'https://github.com/webgptorg/promptbook/discussions/67',
2701
+ /**
2702
+ * Example usages of the MODEL command
2703
+ */
2704
+ examples: ['MODEL VARIANT Chat', 'MODEL NAME `gpt-4`'],
2705
+ /**
2706
+ * Parses the MODEL command
2707
+ */
2708
+ parse: function (input) {
2709
+ var args = input.args, normalized = input.normalized;
2710
+ var availableVariantsMessage = spaceTrim__default["default"](function (block) { return "\n Available variants are:\n ".concat(block(MODEL_VARIANTS.map(function (variantName) {
2711
+ return "- ".concat(variantName).concat(variantName !== 'EMBEDDING' ? '' : ' (Not available in pipeline)');
2712
+ }).join('\n')), "\n "); });
2713
+ // TODO: Make this more elegant and dynamically
2714
+ if (normalized.startsWith('MODEL_VARIANT')) {
2715
+ if (normalized === 'MODEL_VARIANT_CHAT') {
2716
+ return {
2717
+ type: 'MODEL',
2718
+ key: 'modelVariant',
2719
+ value: 'CHAT',
2720
+ };
2721
+ }
2722
+ else if (normalized === 'MODEL_VARIANT_COMPLETION') {
2723
+ return {
2724
+ type: 'MODEL',
2725
+ key: 'modelVariant',
2726
+ value: 'COMPLETION',
2727
+ };
2728
+ // <- Note: [🤖]
2729
+ }
2730
+ else if (normalized.startsWith('MODEL_VARIANT_EMBED')) {
2731
+ spaceTrim__default["default"](function (block) { return "\n Embedding model can not be used in pipeline\n\n ".concat(block(availableVariantsMessage), "\n "); });
2732
+ }
2733
+ else {
2734
+ throw new ParseError(spaceTrim__default["default"](function (block) { return "\n Unknown model variant in command:\n\n ".concat(block(availableVariantsMessage), "\n "); }));
2735
+ }
2736
+ }
2737
+ if (normalized.startsWith('MODEL_NAME')) {
2738
+ return {
2739
+ type: 'MODEL',
2740
+ key: 'modelName',
2741
+ value: args.pop(),
2742
+ };
2743
+ }
2744
+ else {
2745
+ throw new ParseError(spaceTrim__default["default"](function (block) { return "\n Unknown model key in command.\n\n Supported model keys are:\n ".concat(block(['variant', 'name'].join(', ')), "\n\n Example:\n - MODEL VARIANT Chat\n - MODEL NAME gpt-4\n "); }));
2746
+ }
2747
+ },
2748
+ /**
2749
+ * Apply the MODEL command to the `pipelineJson`
2750
+ *
2751
+ * Note: `$` is used to indicate that this function mutates given `pipelineJson`
2752
+ */
2753
+ $applyToPipelineJson: function (command, $pipelineJson) {
2754
+ $pipelineJson.defaultModelRequirements = $pipelineJson.defaultModelRequirements || {};
2755
+ // TODO: [🚜] DRY
2756
+ if ($pipelineJson.defaultModelRequirements[command.key] !== undefined) {
2757
+ if ($pipelineJson.defaultModelRequirements[command.key] === command.value) {
2758
+ console.warn("Multiple commands `MODEL ".concat(command.key, " ").concat(command.value, "` in the pipeline head"));
2759
+ // <- TODO: [🚎][💩] Some better way how to get warnings from pipeline parsing / logic
2760
+ }
2761
+ else {
2762
+ throw new ParseError(spaceTrim__default["default"]("\n Redefinition of `MODEL ".concat(command.key, "` in the pipeline head\n\n You have used:\n 1) `MODEL ").concat(command.key, " ").concat($pipelineJson.defaultModelRequirements[command.key], "`\n 2) `MODEL ").concat(command.key, " ").concat(command.value, "`\n ")));
2763
+ }
2764
+ }
2765
+ $pipelineJson.defaultModelRequirements[command.key] = command.value;
2766
+ },
2767
+ /**
2768
+ * Apply the MODEL command to the `pipelineJson`
2769
+ *
2770
+ * Note: `$` is used to indicate that this function mutates given `taskJson`
2771
+ */
2772
+ $applyToTaskJson: function (command, $taskJson, $pipelineJson) {
2773
+ if ($taskJson.taskType !== 'PROMPT_TASK') {
2774
+ throw new ParseError("MODEL command can only be used in PROMPT_TASK block");
2775
+ }
2776
+ $taskJson.modelRequirements = $taskJson.modelRequirements || {};
2777
+ // TODO: [🚜] DRY
2778
+ if ($taskJson.modelRequirements[command.key] !== undefined) {
2779
+ if ($taskJson.modelRequirements[command.key] === command.value) {
2780
+ console.warn("Multiple commands `MODEL ".concat({
2781
+ modelName: 'NAME',
2782
+ modelVariant: 'VARIANT',
2783
+ maxTokens: '???',
2784
+ }[command.key], " ").concat(command.value, "` in the task \"").concat($taskJson.title || $taskJson.name, "\""));
2785
+ }
2786
+ else {
2787
+ throw new ParseError(spaceTrim__default["default"]("\n Redefinition of MODEL `".concat(command.key, "` in the task \"").concat($taskJson.title || $taskJson.name, "\"\n\n You have used:\n - MODEL ").concat(command.key, " ").concat($taskJson.modelRequirements[command.key], "\n - MODEL ").concat(command.key, " ").concat(command.value, "\n ")));
2788
+ }
2789
+ }
2790
+ if (command.value === ($pipelineJson.defaultModelRequirements || {})[command.key]) {
2791
+ console.log(spaceTrim__default["default"]("\n Setting MODEL `".concat(command.key, "` in the task \"").concat($taskJson.title || $taskJson.name, "\" to the same value as in the pipeline head\n\n In pipeline head:\n - MODEL ").concat(command.key, " ").concat(($pipelineJson.defaultModelRequirements || {})[command.key], "\n\n But same value is used in the task:\n - MODEL ").concat(command.key, " ").concat(command.value, "\n ")));
2792
+ }
2793
+ $taskJson.modelRequirements[command.key] = command.value;
2794
+ },
2795
+ /**
2796
+ * Converts the MODEL command back to string
2797
+ *
2798
+ * Note: This is used in `pipelineJsonToString` utility
2799
+ */
2800
+ stringify: function (command) {
2801
+ return "---"; // <- TODO: [🛋] Implement
2802
+ },
2803
+ /**
2804
+ * Reads the MODEL command from the `PipelineJson`
2805
+ *
2806
+ * Note: This is used in `pipelineJsonToString` utility
2807
+ */
2808
+ takeFromPipelineJson: function (pipelineJson) {
2809
+ throw new NotYetImplementedError("[\uD83D\uDECB] Not implemented yet"); // <- TODO: [🛋] Implement
2810
+ },
2811
+ /**
2812
+ * Reads the MODEL command from the `TaskJson`
2813
+ *
2814
+ * Note: This is used in `pipelineJsonToString` utility
2815
+ */
2816
+ takeFromTaskJson: function ($taskJson) {
2817
+ throw new NotYetImplementedError("[\uD83D\uDECB] Not implemented yet"); // <- TODO: [🛋] Implement
2818
+ },
2819
+ };
2820
+
2821
+ /**
2822
+ * Parses the parameter command
2823
+ *
2824
+ * @see `documentationUrl` for more details
2825
+ * @public exported from `@promptbook/editable`
2826
+ */
2827
+ var parameterCommandParser = {
2828
+ /**
2829
+ * Name of the command
2830
+ */
2831
+ name: 'PARAMETER',
2832
+ /**
2833
+ * Aliases for the PARAMETER command
2834
+ */
2835
+ aliasNames: ['PARAM', 'INPUT_PARAM', 'OUTPUT_PARAM', 'INPUT_PARAMETER', 'OUTPUT_PARAMETER'],
2836
+ /*
2837
+ Note: [🦈] No need for extra alias name because it is already preprocessed
2838
+ */
2839
+ /**
2840
+ * BOILERPLATE command can be used in:
2841
+ */
2842
+ isUsedInPipelineHead: true,
2843
+ isUsedInPipelineTask: true,
2844
+ /**
2845
+ * Description of the PARAMETER command
2846
+ */
2847
+ description: "Describes one parameter of the task",
2848
+ /**
2849
+ * Link to documentation
2850
+ */
2851
+ documentationUrl: 'https://github.com/webgptorg/promptbook/discussions/68',
2852
+ /**
2853
+ * Example usages of the PARAMETER command
2854
+ */
2855
+ examples: ['PARAMETER {title} Title of the book', 'OUTPUT PARAMETER {websiteContent} Content of the book'],
2856
+ /**
2857
+ * Parses the PARAMETER command
2858
+ */
2859
+ parse: function (input) {
2860
+ var normalized = input.normalized, args = input.args, raw = input.raw;
2861
+ var parameterNameRaw = args.shift() || '';
2862
+ var parameterDescriptionRaw = args.join(' ');
2863
+ // <- TODO: When [🥶] fixed, change to:
2864
+ // > const parameterDescriptionRaw = rawArgs.split(parameterNameRaw).join('').trim();
2865
+ if (parameterDescriptionRaw && parameterDescriptionRaw.match(/\{(?<embeddedParameterName>[a-z0-9_]+)\}/im)) {
2866
+ throw new ParseError(spaceTrim__default["default"](function (block) { return "\n Parameter `{".concat(parameterNameRaw, "}` can not contain another parameter in description\n\n The description:\n ").concat(block(parameterDescriptionRaw), "\n "); }));
2867
+ }
2868
+ var isInput = normalized.startsWith('INPUT');
2869
+ var isOutput = normalized.startsWith('OUTPUT');
2870
+ if (raw.startsWith('> {')) {
2871
+ isInput = false;
2872
+ isOutput = false;
2873
+ }
2874
+ var parameterName = validateParameterName(parameterNameRaw);
2875
+ var parameterDescription = parameterDescriptionRaw.trim() || null;
2876
+ return {
2877
+ type: 'PARAMETER',
2878
+ parameterName: parameterName,
2879
+ parameterDescription: parameterDescription,
2880
+ isInput: isInput,
2881
+ isOutput: isOutput,
2882
+ };
2883
+ },
2884
+ /**
2885
+ * Apply the PARAMETER command to the `pipelineJson`
2886
+ *
2887
+ * Note: `$` is used to indicate that this function mutates given `pipelineJson`
2888
+ */
2889
+ $applyToPipelineJson: function (command, $pipelineJson) {
2890
+ // Note: [🍣] Do nothing, its application is implemented separately in `parsePipeline`
2891
+ },
2892
+ /**
2893
+ * Apply the PARAMETER command to the `pipelineJson`
2894
+ *
2895
+ * Note: `$` is used to indicate that this function mutates given `taskJson`
2896
+ */
2897
+ $applyToTaskJson: function (command, $taskJson, $pipelineJson) {
2898
+ // Note: [🍣] Do nothing, its application is implemented separately in `parsePipeline`
2899
+ },
2900
+ /**
2901
+ * Converts the PARAMETER command back to string
2902
+ *
2903
+ * Note: This is used in `pipelineJsonToString` utility
2904
+ */
2905
+ stringify: function (command) {
2906
+ return "---"; // <- TODO: [🛋] Implement
2907
+ },
2908
+ /**
2909
+ * Reads the PARAMETER command from the `PipelineJson`
2910
+ *
2911
+ * Note: This is used in `pipelineJsonToString` utility
2912
+ */
2913
+ takeFromPipelineJson: function (pipelineJson) {
2914
+ throw new NotYetImplementedError("[\uD83D\uDECB] Not implemented yet"); // <- TODO: [🛋] Implement
2915
+ },
2916
+ /**
2917
+ * Reads the PARAMETER command from the `TaskJson`
2918
+ *
2919
+ * Note: This is used in `pipelineJsonToString` utility
2920
+ */
2921
+ takeFromTaskJson: function ($taskJson) {
2922
+ throw new NotYetImplementedError("[\uD83D\uDECB] Not implemented yet"); // <- TODO: [🛋] Implement
2923
+ },
2924
+ };
2925
+
2926
+ /**
2927
+ * Parses the persona command
2928
+ *
2929
+ * @see `documentationUrl` for more details
2930
+ * @public exported from `@promptbook/editable`
2931
+ */
2932
+ var personaCommandParser = {
2933
+ /**
2934
+ * Name of the command
2935
+ */
2936
+ name: 'PERSONA',
2937
+ /**
2938
+ * Aliases for the PERSONA command
2939
+ */
2940
+ aliasNames: ['PERSON'],
2941
+ /**
2942
+ * PERSONA command can be used in:
2943
+ */
2944
+ isUsedInPipelineHead: true,
2945
+ isUsedInPipelineTask: true,
2946
+ /**
2947
+ * Description of the PERSONA command
2948
+ */
2949
+ description: "Persona command is used to specify who the system is, it will be transformed into system message, top_t,...",
2950
+ /**
2951
+ * Link to documentation
2952
+ */
2953
+ documentationUrl: 'https://github.com/webgptorg/promptbook/discussions/22',
2954
+ /**
2955
+ * Example usages of the PERSONA command
2956
+ */
2957
+ examples: ['PERSONA Jane, skilled copywriter', 'PERSONA Joe, male 28 years old, programmer'],
2958
+ /**
2959
+ * Parses the PERSONA command
2960
+ */
2961
+ parse: function (input) {
2962
+ var rawArgs = input.rawArgs;
2963
+ var _a = __read(rawArgs.split(/[,;:]/, 2), 2), personaNameRaw = _a[0], personaDescriptionRaw = _a[1];
2964
+ var personaName = (personaNameRaw || '').trim();
2965
+ if (personaName === '') {
2966
+ throw new ParseError("You must set name for the persona");
2967
+ }
2968
+ var personaDescription = (personaDescriptionRaw || '').trim();
2969
+ if (personaDescription === '') {
2970
+ personaDescription = null;
2971
+ }
2972
+ return {
2973
+ type: 'PERSONA',
2974
+ personaName: personaName,
2975
+ personaDescription: personaDescription,
2976
+ };
2977
+ },
2978
+ /**
2979
+ * Apply the PERSONA command to the `pipelineJson`
2980
+ *
2981
+ * Note: `$` is used to indicate that this function mutates given `pipelineJson`
2982
+ */
2983
+ $applyToPipelineJson: function (command, $pipelineJson) {
2984
+ $applyToTaskJson(command, null, $pipelineJson);
2985
+ },
2986
+ $applyToTaskJson: $applyToTaskJson,
2987
+ /**
2988
+ * Converts the PERSONA command back to string
2989
+ *
2990
+ * Note: This is used in `pipelineJsonToString` utility
2991
+ */
2992
+ stringify: function (command) {
2993
+ return "---"; // <- TODO: [🛋] Implement
2994
+ },
2995
+ /**
2996
+ * Reads the PERSONA command from the `PipelineJson`
2997
+ *
2998
+ * Note: This is used in `pipelineJsonToString` utility
2999
+ */
3000
+ takeFromPipelineJson: function (pipelineJson) {
3001
+ throw new NotYetImplementedError("[\uD83D\uDECB] Not implemented yet"); // <- TODO: [🛋] Implement
3002
+ },
3003
+ /**
3004
+ * Reads the PERSONA command from the `TaskJson`
3005
+ *
3006
+ * Note: This is used in `pipelineJsonToString` utility
3007
+ */
3008
+ takeFromTaskJson: function ($taskJson) {
3009
+ throw new NotYetImplementedError("[\uD83D\uDECB] Not implemented yet"); // <- TODO: [🛋] Implement
3010
+ },
3011
+ };
3012
+ /**
3013
+ * Apply the PERSONA command to the `pipelineJson`
3014
+ *
3015
+ * Note: `$` is used to indicate that this function mutates given `taskJson`
3016
+ */
3017
+ function $applyToTaskJson(command, $taskJson, $pipelineJson) {
3018
+ var personaName = command.personaName, personaDescription = command.personaDescription;
3019
+ if ($taskJson !== null) {
3020
+ if ($taskJson.taskType !== 'PROMPT_TASK') {
3021
+ throw new ParseError("PERSONA command can be used only in PROMPT_TASK block");
3022
+ }
3023
+ $taskJson.personaName = personaName;
3024
+ }
3025
+ var persona = $pipelineJson.personas.find(function (persona) { return persona.name === personaName; });
3026
+ if (persona === undefined) {
3027
+ $pipelineJson.personas.push({
3028
+ name: personaName,
3029
+ description: personaDescription || '',
3030
+ });
3031
+ return;
3032
+ }
3033
+ if (persona.description === personaDescription) {
3034
+ return;
3035
+ }
3036
+ if (personaDescription === null) {
3037
+ return;
3038
+ }
3039
+ if (persona.description === '') {
3040
+ persona.description = personaDescription;
3041
+ return;
3042
+ }
3043
+ console.warn(spaceTrim__default["default"]("\n\n Persona \"".concat(personaName, "\" is defined multiple times with different description:\n\n First definition:\n ").concat(persona.description, "\n\n Second definition:\n ").concat(personaDescription, "\n\n ")));
3044
+ persona.description += spaceTrim__default["default"]('\n\n' + personaDescription);
3045
+ }
3046
+
3047
+ /**
3048
+ * @@@
3049
+ *
3050
+ * @param javascriptName @@@
3051
+ * @returns @@@
3052
+ * @public exported from `@promptbook/utils`
3053
+ */
3054
+ function isValidJavascriptName(javascriptName) {
3055
+ if (typeof javascriptName !== 'string') {
3056
+ return false;
3057
+ }
3058
+ return /^[a-zA-Z_$][0-9a-zA-Z_$]*$/i.test(javascriptName);
3059
+ }
3060
+
3061
+ /**
3062
+ * Parses the postprocess command
3063
+ *
3064
+ * @see `documentationUrl` for more details
3065
+ * @public exported from `@promptbook/editable`
3066
+ */
3067
+ var postprocessCommandParser = {
3068
+ /**
3069
+ * Name of the command
3070
+ */
3071
+ name: 'POSTPROCESS',
3072
+ aliasNames: ['POSTPROCESSING', 'PP'],
3073
+ /**
3074
+ * BOILERPLATE command can be used in:
3075
+ */
3076
+ isUsedInPipelineHead: false,
3077
+ isUsedInPipelineTask: true,
3078
+ /**
3079
+ * Description of the POSTPROCESS command
3080
+ */
3081
+ description: "Defines the postprocess function to be used on the result from LLM and before the result is validated",
3082
+ /**
3083
+ * Link to documentation
3084
+ */
3085
+ documentationUrl: 'https://github.com/webgptorg/promptbook/discussions/31',
3086
+ /**
3087
+ * Example usages of the POSTPROCESS command
3088
+ */
3089
+ examples: [
3090
+ 'POSTPROCESS unwrapResult' /* <- TODO: Make it `POSTPROCESS` examples dynamic, load from all possible postprocess functions */,
3091
+ ],
3092
+ /**
3093
+ * Parses the POSTPROCESS command
3094
+ */
3095
+ parse: function (input) {
3096
+ var args = input.args;
3097
+ var functionName = args.pop();
3098
+ if (functionName === undefined) {
3099
+ throw new ParseError("Postprocess function name is required");
3100
+ }
3101
+ if (!isValidJavascriptName(functionName)) {
3102
+ throw new ParseError("Invalid postprocess function name \"".concat(functionName, "\""));
3103
+ }
3104
+ if (args.length > 0) {
3105
+ throw new ParseError("Can not have more than one postprocess function");
3106
+ }
3107
+ return {
3108
+ type: 'POSTPROCESS',
3109
+ functionName: functionName,
3110
+ };
3111
+ },
3112
+ /**
3113
+ * Apply the POSTPROCESS command to the `pipelineJson`
3114
+ *
3115
+ * Note: `$` is used to indicate that this function mutates given `taskJson`
3116
+ */
3117
+ $applyToTaskJson: function (command, $taskJson) {
3118
+ $taskJson.postprocessingFunctionNames = $taskJson.postprocessingFunctionNames || [];
3119
+ $taskJson.postprocessingFunctionNames.push(command.functionName);
3120
+ },
3121
+ /**
3122
+ * Converts the POSTPROCESS command back to string
3123
+ *
3124
+ * Note: This is used in `pipelineJsonToString` utility
3125
+ */
3126
+ stringify: function (command) {
3127
+ return "---"; // <- TODO: [🛋] Implement
3128
+ },
3129
+ /**
3130
+ * Reads the POSTPROCESS command from the `TaskJson`
3131
+ *
3132
+ * Note: This is used in `pipelineJsonToString` utility
3133
+ */
3134
+ takeFromTaskJson: function ($taskJson) {
3135
+ throw new NotYetImplementedError("[\uD83D\uDECB] Not implemented yet"); // <- TODO: [🛋] Implement
3136
+ },
3137
+ };
3138
+
3139
+ /**
3140
+ * All available task types
3141
+ *
3142
+ * There is is distinction between task types and section types
3143
+ * - Every section in markdown has its SectionType
3144
+ * - Some sections are tasks but other can be non-task sections
3145
+ *
3146
+ * @public exported from `@promptbook/core`
3147
+ */
3148
+ var TaskTypes = [
3149
+ 'PROMPT',
3150
+ 'SIMPLE',
3151
+ 'SCRIPT',
3152
+ 'DIALOG',
3153
+ // <- [🅱]
3154
+ ];
3155
+
3156
+ /**
3157
+ * All available sections which are not tasks
3158
+ *
3159
+ * @public exported from `@promptbook/core`
3160
+ */
3161
+ var NonTaskSectionTypes = ['EXAMPLE', 'KNOWLEDGE', 'INSTRUMENT', 'ACTION'];
3162
+ /**
3163
+ * All available section types
3164
+ *
3165
+ * There is is distinction between task types and section types
3166
+ * - Every section in markdown has its SectionType
3167
+ * - Some sections are tasks but other can be non-task sections
3168
+ *
3169
+ * @public exported from `@promptbook/core`
3170
+ */
3171
+ var SectionTypes = __spreadArray(__spreadArray([], __read(TaskTypes.map(function (TaskType) { return "".concat(TaskType, "_TASK"); })), false), __read(NonTaskSectionTypes), false);
3172
+
3173
+ /**
3174
+ * Parses the section command
3175
+ *
3176
+ * @see `documentationUrl` for more details
3177
+ * @public exported from `@promptbook/editable`
3178
+ */
3179
+ var sectionCommandParser = {
3180
+ /**
3181
+ * Name of the command
3182
+ */
3183
+ name: 'SECTION',
3184
+ /**
3185
+ * Aliases for the SECTION command
3186
+ */
3187
+ aliasNames: [
3188
+ 'PROMPT',
3189
+ 'SIMPLE',
3190
+ 'SCRIPT',
3191
+ 'DIALOG',
3192
+ 'SAMPLE',
3193
+ 'EXAMPLE',
3194
+ 'KNOWLEDGE',
3195
+ 'INSTRUMENT',
3196
+ 'ACTION', // <- Note: [⛱]
3197
+ ],
3198
+ /**
3199
+ * Aliases for the SECTION command
3200
+ */
3201
+ deprecatedNames: ['TEMPLATE', 'BLOCK', 'EXECUTE'],
3202
+ /**
3203
+ * BOILERPLATE command can be used in:
3204
+ */
3205
+ isUsedInPipelineHead: false,
3206
+ isUsedInPipelineTask: true,
3207
+ /**
3208
+ * Description of the SECTION command
3209
+ */
3210
+ description: "Defines the purpose of the markdown section - if its a task and which type or something else",
3211
+ /**
3212
+ * Link to documentation
3213
+ */
3214
+ documentationUrl: 'https://github.com/webgptorg/promptbook/discussions/64',
3215
+ /**
3216
+ * Example usages of the SECTION command
3217
+ */
3218
+ examples: [
3219
+ // Short form:
3220
+ 'PROMPT',
3221
+ 'SIMPLE',
3222
+ 'SCRIPT',
3223
+ 'DIALOG',
3224
+ // <- [🅱]
3225
+ 'EXAMPLE',
3226
+ 'KNOWLEDGE',
3227
+ 'INSTRUMENT',
3228
+ 'ACTION',
3229
+ // -----------------
3230
+ // Recommended (reversed) form:
3231
+ 'PROMPT SECTION',
3232
+ 'SIMPLE SECTION',
3233
+ 'SCRIPT SECTION',
3234
+ 'DIALOG SECTION',
3235
+ // <- [🅱]
3236
+ 'EXAMPLE SECTION',
3237
+ 'KNOWLEDGE SECTION',
3238
+ 'INSTRUMENT SECTION',
3239
+ 'ACTION SECTION',
3240
+ // -----------------
3241
+ // Standard form:
3242
+ 'SECTION PROMPT',
3243
+ 'SECTION SIMPLE',
3244
+ 'SECTION SCRIPT',
3245
+ 'SECTION DIALOG',
3246
+ // <- [🅱]
3247
+ 'SECTION EXAMPLE',
3248
+ 'SECTION KNOWLEDGE',
3249
+ 'SECTION INSTRUMENT',
3250
+ 'SECTION ACTION',
3251
+ ],
3252
+ // TODO: [♓️] order: -10 /* <- Note: Putting before other commands */
3253
+ /**
3254
+ * Parses the SECTION command
3255
+ */
3256
+ parse: function (input) {
3257
+ var normalized = input.normalized;
3258
+ normalized = normalized.split('SAMPLE').join('EXAMPLE');
3259
+ normalized = normalized.split('EXECUTE_').join('');
3260
+ normalized = normalized.split('DIALOGUE').join('DIALOG');
3261
+ var taskTypes = SectionTypes.filter(function (sectionType) {
3262
+ return normalized.includes(sectionType.split('_TASK').join(''));
3263
+ });
3264
+ if (taskTypes.length !== 1) {
3265
+ throw new ParseError(spaceTrim__default["default"](function (block) { return "\n Unknown section type \"".concat(normalized, "\"\n\n Supported section types are:\n ").concat(block(SectionTypes.join(', ')), "\n "); }));
3266
+ }
3267
+ var taskType = taskTypes[0];
3268
+ return {
3269
+ type: 'SECTION',
3270
+ taskType: taskType,
3271
+ };
3272
+ },
3273
+ /**
3274
+ * Apply the SECTION command to the `pipelineJson`
3275
+ *
3276
+ * Note: `$` is used to indicate that this function mutates given `taskJson`
3277
+ */
3278
+ $applyToTaskJson: function (command, $taskJson, $pipelineJson) {
3279
+ if ($taskJson.isSectionTypeSet === true) {
3280
+ throw new ParseError(spaceTrim__default["default"]("\n Section type is already defined in the section.\n It can be defined only once.\n "));
3281
+ }
3282
+ $taskJson.isSectionTypeSet = true;
3283
+ // TODO: [🍧][💩] Rearrange better - but at bottom and unwrap from function
3284
+ var expectResultingParameterName = function () {
3285
+ if ($taskJson.resultingParameterName) {
3286
+ return;
3287
+ }
3288
+ throw new ParseError("Task section and example section must end with return statement -> {parameterName}");
3289
+ };
3290
+ if ($taskJson.content === undefined) {
3291
+ throw new UnexpectedError("Content is missing in the taskJson - probbably commands are applied in wrong order");
3292
+ }
3293
+ if (command.taskType === 'EXAMPLE') {
3294
+ expectResultingParameterName();
3295
+ var parameter = $pipelineJson.parameters.find(function (param) { return param.name === $taskJson.resultingParameterName; });
3296
+ if (parameter === undefined) {
3297
+ // TODO: !!6 Change to logic error for higher level abstraction of chatbot to work
3298
+ throw new ParseError("Parameter `{".concat($taskJson.resultingParameterName, "}` is not defined so can not define example value of it"));
3299
+ }
3300
+ parameter.exampleValues = parameter.exampleValues || [];
3301
+ parameter.exampleValues.push($taskJson.content);
3302
+ $taskJson.isTask = false;
3303
+ return;
3304
+ }
3305
+ if (command.taskType === 'KNOWLEDGE') {
3306
+ knowledgeCommandParser.$applyToPipelineJson({
3307
+ type: 'KNOWLEDGE',
3308
+ knowledgeSourceContent: $taskJson.content, // <- TODO: [🐝][main] !!3 Work with KNOWLEDGE which not referring to the source file or website, but its content itself
3309
+ }, $pipelineJson);
3310
+ $taskJson.isTask = false;
3311
+ return;
3312
+ }
3313
+ if (command.taskType === 'ACTION') {
3314
+ console.error(new NotYetImplementedError('Actions are not implemented yet'));
3315
+ $taskJson.isTask = false;
3316
+ return;
3317
+ }
3318
+ if (command.taskType === 'INSTRUMENT') {
3319
+ console.error(new NotYetImplementedError('Instruments are not implemented yet'));
3320
+ $taskJson.isTask = false;
3321
+ return;
3322
+ }
3323
+ expectResultingParameterName();
3324
+ $taskJson.taskType = command.taskType;
3325
+ $taskJson.isTask = true;
3326
+ },
3327
+ /**
3328
+ * Converts the SECTION command back to string
3329
+ *
3330
+ * Note: This is used in `pipelineJsonToString` utility
3331
+ */
3332
+ stringify: function (command) {
3333
+ return "---"; // <- TODO: [🛋] Implement
3334
+ },
3335
+ /**
3336
+ * Reads the SECTION command from the `TaskJson`
3337
+ *
3338
+ * Note: This is used in `pipelineJsonToString` utility
3339
+ */
3340
+ takeFromTaskJson: function ($taskJson) {
3341
+ throw new NotYetImplementedError("[\uD83D\uDECB] Not implemented yet"); // <- TODO: [🛋] Implement
3342
+ },
3343
+ };
3344
+ /**
3345
+ * Note: [⛱] There are two types of KNOWLEDGE, ACTION and INSTRUMENT commands:
3346
+ * 1) There are commands `KNOWLEDGE`, `ACTION` and `INSTRUMENT` used in the pipeline head, they just define the knowledge, action or instrument as single line after the command
3347
+ * - KNOWLEDGE Look at https://en.wikipedia.org/wiki/Artificial_intelligence
3348
+ * 2) `KNOWLEDGE SECTION` which has short form `KNOWLEDGE` is used in the sectiom, does not refer the line itself, but the content of the section block
3349
+ * - KNOWLEDGE SECTION
3350
+ *
3351
+ * ```
3352
+ * Look at https://en.wikipedia.org/wiki/Artificial_intelligence
3353
+ * ```
3354
+ */
3355
+
3356
+ /**
3357
+ * Checks if an URL is reserved for private networks or localhost.
3358
+ *
3359
+ * Note: There are two simmilar functions:
3360
+ * - `isUrlOnPrivateNetwork` which tests full URL
3361
+ * - `isHostnameOnPrivateNetwork` *(this one)* which tests just hostname
3362
+ *
3363
+ * @public exported from `@promptbook/utils`
3364
+ */
3365
+ function isHostnameOnPrivateNetwork(hostname) {
3366
+ if (hostname === 'example.com' ||
3367
+ hostname === 'localhost' ||
3368
+ hostname.endsWith('.localhost') ||
3369
+ hostname.endsWith('.local') ||
3370
+ hostname.endsWith('.test') ||
3371
+ hostname === '127.0.0.1' ||
3372
+ hostname === '::1') {
3373
+ return true;
3374
+ }
3375
+ if (hostname.includes(':')) {
3376
+ // IPv6
3377
+ var ipParts = hostname.split(':');
3378
+ return ipParts[0] === 'fc00' || ipParts[0] === 'fd00' || ipParts[0] === 'fe80';
3379
+ }
3380
+ else {
3381
+ // IPv4
3382
+ var ipParts = hostname.split('.').map(function (part) { return Number.parseInt(part, 10); });
3383
+ return (ipParts[0] === 10 ||
3384
+ (ipParts[0] === 172 && ipParts[1] >= 16 && ipParts[1] <= 31) ||
3385
+ (ipParts[0] === 192 && ipParts[1] === 168));
3386
+ }
3387
+ }
3388
+
3389
+ /**
3390
+ * Checks if an IP address or hostname is reserved for private networks or localhost.
3391
+ *
3392
+ * Note: There are two simmilar functions:
3393
+ * - `isUrlOnPrivateNetwork` *(this one)* which tests full URL
3394
+ * - `isHostnameOnPrivateNetwork` which tests just hostname
3395
+ *
3396
+ * @param {string} ipAddress - The IP address to check.
3397
+ * @returns {boolean} Returns true if the IP address is reserved for private networks or localhost, otherwise false.
3398
+ * @public exported from `@promptbook/utils`
3399
+ */
3400
+ function isUrlOnPrivateNetwork(url) {
3401
+ if (typeof url === 'string') {
3402
+ url = new URL(url);
3403
+ }
3404
+ return isHostnameOnPrivateNetwork(url.hostname);
3405
+ }
3406
+
3407
+ /**
3408
+ * Tests if given string is valid pipeline URL URL.
3409
+ *
3410
+ * Note: There are two simmilar functions:
3411
+ * - `isValidUrl` which tests any URL
3412
+ * - `isValidPipelineUrl` *(this one)* which tests just pipeline URL
3413
+ *
3414
+ * @public exported from `@promptbook/utils`
3415
+ */
3416
+ function isValidPipelineUrl(url) {
3417
+ if (!isValidUrl(url)) {
3418
+ return false;
3419
+ }
3420
+ if (!url.startsWith('https://')) {
3421
+ return false;
3422
+ }
3423
+ if (url.includes('#')) {
3424
+ // TODO: [🐠]
3425
+ return false;
3426
+ }
3427
+ if (isUrlOnPrivateNetwork(url)) {
3428
+ return false;
3429
+ }
3430
+ return true;
3431
+ }
3432
+ /**
3433
+ * TODO: [🐠] Maybe more info why the URL is invalid
3434
+ */
3435
+
3436
+ /**
3437
+ * Parses the url command
3438
+ *
3439
+ * @see `documentationUrl` for more details
3440
+ * @public exported from `@promptbook/editable`
3441
+ */
3442
+ var urlCommandParser = {
3443
+ /**
3444
+ * Name of the command
3445
+ */
3446
+ name: 'URL',
3447
+ aliasNames: ['PIPELINE_URL'],
3448
+ /*
3449
+ Note: [🛵] No need for this alias name because it is already preprocessed
3450
+ aliasNames: ['HTTPS'],
3451
+ */
3452
+ /**
3453
+ * BOILERPLATE command can be used in:
3454
+ */
3455
+ isUsedInPipelineHead: true,
3456
+ isUsedInPipelineTask: false,
3457
+ /**
3458
+ * Description of the URL command
3459
+ */
3460
+ description: "Declares unique URL for the pipeline",
3461
+ /**
3462
+ * Link to documentation
3463
+ */
3464
+ documentationUrl: 'https://github.com/webgptorg/promptbook/discussions/70',
3465
+ /**
3466
+ * Example usages of the URL command
3467
+ */
3468
+ examples: [
3469
+ 'PIPELINE URL https://promptbook.studio/library/write-cv.book.md',
3470
+ 'URL https://promptbook.studio/library/write-cv.book.md',
3471
+ 'https://promptbook.studio/library/write-cv.book.md',
3472
+ ],
3473
+ /**
3474
+ * Parses the URL command
3475
+ */
3476
+ parse: function (input) {
3477
+ var args = input.args;
3478
+ var pipelineUrl = args.pop();
3479
+ if (pipelineUrl === undefined) {
3480
+ throw new ParseError("URL is required");
3481
+ }
3482
+ // TODO: [🧠][🚲] This should be maybe tested as logic not parse
3483
+ if (!isValidPipelineUrl(pipelineUrl)) {
3484
+ throw new ParseError("Invalid pipeline URL \"".concat(pipelineUrl, "\""));
3485
+ }
3486
+ if (args.length > 0) {
3487
+ throw new ParseError("Can not have more than one pipeline URL");
3488
+ }
3489
+ /*
3490
+ TODO: [🐠 Maybe more info from `isValidPipelineUrl`:
3491
+ if (pipelineUrl.protocol !== 'https:') {
3492
+ throw new ParseError(`Protocol must be HTTPS`);
3493
+ }
3494
+
3495
+ if (pipelineUrl.hash !== '') {
3496
+ throw new ParseError(
3497
+ spaceTrim(
3498
+ `
3499
+ URL must not contain hash
3500
+ Hash is used for identification of the section of the pipeline
3501
+ `,
3502
+ ),
3503
+ );
3504
+ }
3505
+ */
3506
+ return {
3507
+ type: 'URL',
3508
+ pipelineUrl: new URL(pipelineUrl),
3509
+ };
3510
+ },
3511
+ /**
3512
+ * Apply the URL command to the `pipelineJson`
3513
+ *
3514
+ * Note: `$` is used to indicate that this function mutates given `pipelineJson`
3515
+ */
3516
+ $applyToPipelineJson: function (command, $pipelineJson) {
3517
+ $pipelineJson.pipelineUrl = command.pipelineUrl.href;
3518
+ },
3519
+ /**
3520
+ * Converts the URL command back to string
3521
+ *
3522
+ * Note: This is used in `pipelineJsonToString` utility
3523
+ */
3524
+ stringify: function (command) {
3525
+ return "---"; // <- TODO: [🛋] Implement
3526
+ },
3527
+ /**
3528
+ * Reads the URL command from the `PipelineJson`
3529
+ *
3530
+ * Note: This is used in `pipelineJsonToString` utility
3531
+ */
3532
+ takeFromPipelineJson: function (pipelineJson) {
3533
+ throw new NotYetImplementedError("[\uD83D\uDECB] Not implemented yet"); // <- TODO: [🛋] Implement
3534
+ },
3535
+ };
3536
+
3537
+ /**
3538
+ * Parses the action command
3539
+ *
3540
+ * @see `documentationUrl` for more details
3541
+ * @public exported from `@promptbook/editable`
3542
+ */
3543
+ var actionCommandParser = {
3544
+ /**
3545
+ * Name of the command
3546
+ */
3547
+ name: 'ACTION',
3548
+ /**
3549
+ * ACTION command can be used in:
3550
+ */
3551
+ isUsedInPipelineHead: true,
3552
+ isUsedInPipelineTask: false,
3553
+ /**
3554
+ * Description of the ACTION command
3555
+ */
3556
+ description: "Actions influences from the pipeline or task into external world. Like turning on a light, sending an email, etc.",
3557
+ /**
3558
+ * Link to documentation
3559
+ */
3560
+ documentationUrl: 'https://github.com/webgptorg/promptbook/discussions/72',
3561
+ /**
3562
+ * Example usages of the ACTION command
3563
+ */
3564
+ examples: ['ACTION'],
3565
+ /**
3566
+ * Parses the ACTION command
3567
+ */
3568
+ parse: function (input) {
3569
+ input.args;
3570
+ return {
3571
+ type: 'ACTION',
3572
+ };
3573
+ },
3574
+ /**
3575
+ * Apply the ACTION command to the `pipelineJson`
3576
+ *
3577
+ * Note: `$` is used to indicate that this function mutates given `pipelineJson`
3578
+ */
3579
+ $applyToPipelineJson: function (command, $pipelineJson) {
3580
+ console.error(new NotYetImplementedError('[🛠] Actions are not implemented yet'));
3581
+ },
3582
+ /**
3583
+ * Converts the ACTION command back to string
3584
+ *
3585
+ * Note: This is used in `pipelineJsonToString` utility
3586
+ */
3587
+ stringify: function (command) {
3588
+ throw new NotYetImplementedError('[🛠] Actions are not implemented yet');
3589
+ },
3590
+ /**
3591
+ * Reads the ACTION command from the `PipelineJson`
3592
+ *
3593
+ * Note: This is used in `pipelineJsonToString` utility
3594
+ */
3595
+ takeFromPipelineJson: function (pipelineJson) {
3596
+ throw new NotYetImplementedError('[🛠] Actions are not implemented yet');
3597
+ },
3598
+ };
3599
+ /**
3600
+ * Note: [⛱] There are two types of ACTION commands *...(read more in [⛱])*
3601
+ */
3602
+
3603
+ /**
3604
+ * Parses the instrument command
3605
+ *
3606
+ * @see `documentationUrl` for more details
3607
+ * @public exported from `@promptbook/editable`
3608
+ */
3609
+ var instrumentCommandParser = {
3610
+ /**
3611
+ * Name of the command
3612
+ */
3613
+ name: 'INSTRUMENT',
3614
+ /**
3615
+ * INSTRUMENT command can be used in:
3616
+ */
3617
+ isUsedInPipelineHead: true,
3618
+ isUsedInPipelineTask: false,
3619
+ /**
3620
+ * Description of the INSTRUMENT command
3621
+ */
3622
+ description: "Instrument command is used to specify the instrument to be used in the pipeline or task like search, calculate, etc.",
3623
+ /**
3624
+ * Link to documentation
3625
+ */
3626
+ documentationUrl: 'https://github.com/webgptorg/promptbook/discussions/71',
3627
+ /**
3628
+ * Example usages of the INSTRUMENT command
3629
+ */
3630
+ examples: ['INSTRUMENT'],
3631
+ /**
3632
+ * Parses the INSTRUMENT command
3633
+ */
3634
+ parse: function (input) {
3635
+ input.args;
3636
+ return {
3637
+ type: 'INSTRUMENT',
3638
+ };
3639
+ },
3640
+ /**
3641
+ * Apply the INSTRUMENT command to the `pipelineJson`
3642
+ *
3643
+ * Note: `$` is used to indicate that this function mutates given `pipelineJson`
3644
+ */
3645
+ $applyToPipelineJson: function (command, $pipelineJson) {
3646
+ console.error(new NotYetImplementedError('[🛠] Instruments are not implemented yet'));
3647
+ },
3648
+ /**
3649
+ * Converts the INSTRUMENT command back to string
3650
+ *
3651
+ * Note: This is used in `pipelineJsonToString` utility
3652
+ */
3653
+ stringify: function (command) {
3654
+ throw new NotYetImplementedError('[🛠] Instruments are not implemented yet');
3655
+ },
3656
+ /**
3657
+ * Reads the INSTRUMENT command from the `PipelineJson`
3658
+ *
3659
+ * Note: This is used in `pipelineJsonToString` utility
3660
+ */
3661
+ takeFromPipelineJson: function (pipelineJson) {
3662
+ throw new NotYetImplementedError('[🛠] Instruments are not implemented yet');
3663
+ },
3664
+ };
3665
+ /**
3666
+ * Note: [⛱] There are two types of INSTRUMENT commands *...(read more in [⛱])*
3667
+ */
3668
+
3669
+ /**
3670
+ * All available command parsers
3671
+ *
3672
+ * @public exported from `@promptbook/editable`
3673
+ */
3674
+ var COMMANDS = [
3675
+ sectionCommandParser,
3676
+ expectCommandParser,
3677
+ formatCommandParser,
3678
+ jokerCommandParser,
3679
+ modelCommandParser,
3680
+ parameterCommandParser,
3681
+ postprocessCommandParser,
3682
+ bookVersionCommandParser,
3683
+ formfactorCommandParser,
3684
+ urlCommandParser,
3685
+ knowledgeCommandParser,
3686
+ actionCommandParser,
3687
+ instrumentCommandParser,
3688
+ personaCommandParser,
3689
+ foreachCommandParser,
3690
+ boilerplateCommandParser, // <- TODO: Only in development, remove in production
3691
+ // <- Note: [♓️][💩] This is the order of the commands in the pipeline, BUT its not used in parsing and before usage maybe it should be done better
3692
+ ];
3693
+ /**
573
3694
  * Note: [💞] Ignore a discrepancy between file name and entity name
574
3695
  */
575
3696
 
3697
+ /**
3698
+ * Gets the parser for the command
3699
+ *
3700
+ * @returns the parser for the command
3701
+ * @throws {UnexpectedError} if the parser is not found
3702
+ *
3703
+ * @public exported from `@promptbook/editable`
3704
+ */
3705
+ function getParserForCommand(command) {
3706
+ var commandParser = COMMANDS.find(function (commandParser) { return commandParser.name === command.type; });
3707
+ if (commandParser === undefined) {
3708
+ throw new UnexpectedError(spaceTrim.spaceTrim(function (block) { return "\n Command ".concat(command.type, " parser is not found\n\n ").concat(block(JSON.stringify(command, null, 4)
3709
+ .split('\n')
3710
+ .map(function (line) { return "> ".concat(line); })
3711
+ .join('\n')), "\n "); }));
3712
+ }
3713
+ return commandParser;
3714
+ }
3715
+
3716
+ /**
3717
+ * Removes Markdown formatting tags from a string.
3718
+ *
3719
+ * @param {string} str - The string to remove Markdown tags from.
3720
+ * @returns {string} The input string with all Markdown tags removed.
3721
+ * @public exported from `@promptbook/markdown-utils`
3722
+ */
3723
+ function removeMarkdownFormatting(str) {
3724
+ // Remove bold formatting
3725
+ str = str.replace(/\*\*(.*?)\*\*/g, '$1');
3726
+ // Remove italic formatting
3727
+ str = str.replace(/\*(.*?)\*/g, '$1');
3728
+ // Remove code formatting
3729
+ str = str.replace(/`(.*?)`/g, '$1');
3730
+ return str;
3731
+ }
3732
+
3733
+ /**
3734
+ * Parses one line of ul/ol to command
3735
+ *
3736
+ * @returns parsed command object
3737
+ * @throws {ParseError} if the command is invalid
3738
+ *
3739
+ * @public exported from `@promptbook/editable`
3740
+ */
3741
+ function parseCommand(raw, usagePlace) {
3742
+ if (raw.includes('\n') || raw.includes('\r')) {
3743
+ throw new ParseError('Command can not contain new line characters' /* <- TODO: [🚞] */);
3744
+ }
3745
+ // TODO: Unit test all this processing and parsing
3746
+ var normalized = raw.trim();
3747
+ normalized = normalized.split('`').join('');
3748
+ normalized = normalized.split('"').join('');
3749
+ normalized = normalized.split("'").join('');
3750
+ normalized = normalized.split('~').join('');
3751
+ normalized = normalized.split('[').join('');
3752
+ normalized = normalized.split(']').join('');
3753
+ normalized = normalized.split('(').join('');
3754
+ normalized = normalized.split(')').join('');
3755
+ normalized = normalizeTo_SCREAMING_CASE(normalized);
3756
+ var items = raw
3757
+ .trim()
3758
+ // Note: [🐡]
3759
+ .split(/^>/)
3760
+ .join('')
3761
+ // ---
3762
+ .trim()
3763
+ .split(/["'`]/)
3764
+ .join('')
3765
+ .trim()
3766
+ // Note: [🛵]:
3767
+ .split(/^http/)
3768
+ .join('URL http')
3769
+ // ---
3770
+ // Note: [🦈]
3771
+ .split(/^{/)
3772
+ .join('PARAMETER {')
3773
+ // ---
3774
+ .split(' ')
3775
+ .map(function (part) { return part.trim(); })
3776
+ .filter(function (item) { return item !== ''; })
3777
+ .map(removeMarkdownFormatting)
3778
+ .map(function (item) { return item.trim(); });
3779
+ if (items.length === 0 || items[0] === '') {
3780
+ throw new ParseError(spaceTrim.spaceTrim(function (block) {
3781
+ return "\n Malformed command:\n - ".concat(raw, "\n\n Supported commands are:\n ").concat(block(getSupportedCommandsMessage()), "\n\n ");
3782
+ }));
3783
+ }
3784
+ // Note: Taking command name from beginning of the line
3785
+ // FOO | BAR Arg1 Arg2 Arg3
3786
+ // FOO BAR | Arg1 Arg2 Arg3
3787
+ for (var commandNameSegmentsCount = 0; commandNameSegmentsCount < Math.min(items.length, 3); commandNameSegmentsCount++) {
3788
+ var commandNameRaw = items.slice(0, commandNameSegmentsCount + 1).join('_');
3789
+ var args = items.slice(commandNameSegmentsCount + 1);
3790
+ var rawArgs = raw
3791
+ .substring(commandNameRaw.length)
3792
+ .trim();
3793
+ var command = parseCommandVariant({ usagePlace: usagePlace, raw: raw, rawArgs: rawArgs, normalized: normalized, args: args, commandNameRaw: commandNameRaw });
3794
+ if (command !== null) {
3795
+ return command;
3796
+ }
3797
+ }
3798
+ // Note: Taking command name from end of the line
3799
+ // Arg1 Arg2 Arg3 | FOO
3800
+ {
3801
+ var commandNameRaw = items.slice(-1).join('_');
3802
+ var args = items.slice(0, -1); // <- Note: This is probbably not correct
3803
+ var rawArgs = raw
3804
+ .substring(0, raw.length - commandNameRaw.length)
3805
+ .trim();
3806
+ var command = parseCommandVariant({ usagePlace: usagePlace, raw: raw, rawArgs: rawArgs, normalized: normalized, args: args, commandNameRaw: commandNameRaw });
3807
+ if (command !== null) {
3808
+ return command;
3809
+ }
3810
+ }
3811
+ throw new ParseError(spaceTrim.spaceTrim(function (block) {
3812
+ return "\n Malformed or unknown command:\n - ".concat(raw, "\n\n Supported commands are:\n ").concat(block(getSupportedCommandsMessage()), "\n\n ");
3813
+ }));
3814
+ }
3815
+ /**
3816
+ * @@@
3817
+ */
3818
+ function getSupportedCommandsMessage() {
3819
+ return COMMANDS.flatMap(function (_a) {
3820
+ var name = _a.name, aliasNames = _a.aliasNames, description = _a.description, documentationUrl = _a.documentationUrl;
3821
+ // <- Note: [🦦] Its strange that this type assertion is needed
3822
+ return __spreadArray([
3823
+ "- **".concat(name, "** ").concat(description, ", see [discussion](").concat(documentationUrl, ")")
3824
+ ], __read((aliasNames || []).map(function (aliasName) { return " - **".concat(aliasName, "** Alias for **").concat(name, "**"); })), false);
3825
+ }).join('\n');
3826
+ }
3827
+ /**
3828
+ * @@@
3829
+ */
3830
+ function parseCommandVariant(input) {
3831
+ var e_1, _a;
3832
+ var commandNameRaw = input.commandNameRaw, usagePlace = input.usagePlace, normalized = input.normalized, args = input.args, raw = input.raw, rawArgs = input.rawArgs;
3833
+ var commandName = normalizeTo_SCREAMING_CASE(commandNameRaw);
3834
+ var _loop_1 = function (commandParser) {
3835
+ // <- Note: [🦦] Its strange that this type assertion is needed
3836
+ var name_1 = commandParser.name, isUsedInPipelineHead = commandParser.isUsedInPipelineHead, isUsedInPipelineTask = commandParser.isUsedInPipelineTask, aliasNames = commandParser.aliasNames, deprecatedNames = commandParser.deprecatedNames, parse = commandParser.parse;
3837
+ if (just(false)) ;
3838
+ else if (usagePlace === 'PIPELINE_HEAD' && !isUsedInPipelineHead) {
3839
+ return "continue";
3840
+ }
3841
+ else if (usagePlace === 'PIPELINE_TASK' && !isUsedInPipelineTask) {
3842
+ return "continue";
3843
+ }
3844
+ var names = __spreadArray(__spreadArray([name_1], __read((aliasNames || [])), false), __read((deprecatedNames || [])), false);
3845
+ if (names.includes(commandName)) {
3846
+ try {
3847
+ return { value: parse({ usagePlace: usagePlace, raw: raw, rawArgs: rawArgs, normalized: normalized, args: args }) };
3848
+ }
3849
+ catch (error) {
3850
+ if (!(error instanceof ParseError)) {
3851
+ throw error;
3852
+ }
3853
+ throw new ParseError(spaceTrim.spaceTrim(function (block) {
3854
+ return "\n Invalid ".concat(commandName, " command:\n\n Your command:\n - ").concat(raw, "\n\n The detailed error:\n ").concat(block(error.message), "\n\n Usage of ").concat(commandName, ":\n ").concat(block(commandParser.examples.map(function (example) { return "- ".concat(example); }).join('\n')), "\n\n All supported commands are:\n ").concat(block(getSupportedCommandsMessage()), "\n\n ");
3855
+ }));
3856
+ }
3857
+ }
3858
+ };
3859
+ try {
3860
+ for (var _b = __values(COMMANDS), _c = _b.next(); !_c.done; _c = _b.next()) {
3861
+ var commandParser = _c.value;
3862
+ var state_1 = _loop_1(commandParser);
3863
+ if (typeof state_1 === "object")
3864
+ return state_1.value;
3865
+ }
3866
+ }
3867
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
3868
+ finally {
3869
+ try {
3870
+ if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
3871
+ }
3872
+ finally { if (e_1) throw e_1.error; }
3873
+ }
3874
+ return null;
3875
+ }
3876
+
3877
+ /**
3878
+ * Function `validatePipelineString` will validate the if the string is a valid pipeline string
3879
+ * It does not check if the string is fully logically correct, but if it is a string that can be a pipeline string or the string looks completely different.
3880
+ *
3881
+ * @param {string} pipelineString the candidate for a pipeline string
3882
+ * @returns {PipelineString} the same string as input, but validated as valid
3883
+ * @throws {ParseError} if the string is not a valid pipeline string
3884
+ * @public exported from `@promptbook/core`
3885
+ */
3886
+ function validatePipelineString(pipelineString) {
3887
+ if (isValidJsonString(pipelineString)) {
3888
+ throw new ParseError('Expected a book, but got a JSON string');
3889
+ }
3890
+ // <- TODO: Implement the validation + add tests when the pipeline logic considered as invalid
3891
+ return pipelineString;
3892
+ }
3893
+ /**
3894
+ * TODO: [🧠][🈴] Where is the best location for this file
3895
+ */
3896
+
3897
+ /**
3898
+ * Removes Markdown (or HTML) comments
3899
+ *
3900
+ * @param {string} content - The string to remove comments from.
3901
+ * @returns {string} The input string with all comments removed.
3902
+ * @public exported from `@promptbook/markdown-utils`
3903
+ */
3904
+ function removeMarkdownComments(content) {
3905
+ return spaceTrim.spaceTrim(content.replace(/<!--(.*?)-->/gs, ''));
3906
+ }
3907
+
3908
+ /**
3909
+ * @@@
3910
+ *
3911
+ * @public exported from `@promptbook/editable`
3912
+ */
3913
+ function isFlatPipeline(pipelineString) {
3914
+ pipelineString = removeMarkdownComments(pipelineString);
3915
+ pipelineString = spaceTrim__default["default"](pipelineString);
3916
+ var isMarkdownBeginningWithHeadline = pipelineString.startsWith('# ');
3917
+ var isLastLineReturnStatement = pipelineString.split('\n').pop().split('`').join('').startsWith('->');
3918
+ // TODO: Also (double)check
3919
+ // > const usedCommands
3920
+ // > const isBlocksUsed
3921
+ // > const returnStatementCount
3922
+ var isFlat = !isMarkdownBeginningWithHeadline && isLastLineReturnStatement;
3923
+ return isFlat;
3924
+ }
3925
+
3926
+ /**
3927
+ * @@@
3928
+ *
3929
+ * @public exported from `@promptbook/editable`
3930
+ */
3931
+ function deflatePipeline(pipelineString) {
3932
+ if (!isFlatPipeline(pipelineString)) {
3933
+ return pipelineString;
3934
+ }
3935
+ var pipelineStringLines = pipelineString.split('\n');
3936
+ var returnStatement = pipelineStringLines.pop();
3937
+ var prompt = spaceTrim__default["default"](pipelineStringLines.join('\n'));
3938
+ pipelineString = validatePipelineString(spaceTrim__default["default"](function (block) { return "\n # ".concat(DEFAULT_BOOK_TITLE, "\n\n ## Prompt\n\n ```\n ").concat(block(prompt), "\n ```\n\n ").concat(returnStatement, "\n "); }));
3939
+ // <- TODO: Maybe use book` notation
3940
+ return pipelineString;
3941
+ }
3942
+ /**
3943
+ * TODO: Unit test
3944
+ */
3945
+
3946
+ /**
3947
+ * @@@
3948
+ *
3949
+ * @public exported from `@promptbook/editable`
3950
+ */
3951
+ function addPipelineCommand(options) {
3952
+ var e_1, _a;
3953
+ var commandString = options.commandString, pipelineString = options.pipelineString;
3954
+ var deflatedPipelineString = deflatePipeline(pipelineString);
3955
+ var lines = deflatedPipelineString.split('\n');
3956
+ var newLines = [];
3957
+ var isCommandAdded = false;
3958
+ try {
3959
+ for (var lines_1 = __values(lines), lines_1_1 = lines_1.next(); !lines_1_1.done; lines_1_1 = lines_1.next()) {
3960
+ var line = lines_1_1.value;
3961
+ // Add command before second (or more) heading
3962
+ if (!isCommandAdded && line.startsWith('##')) {
3963
+ newLines.push("- ".concat(commandString));
3964
+ newLines.push('');
3965
+ isCommandAdded = true;
3966
+ }
3967
+ newLines.push(line);
3968
+ }
3969
+ }
3970
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
3971
+ finally {
3972
+ try {
3973
+ if (lines_1_1 && !lines_1_1.done && (_a = lines_1.return)) _a.call(lines_1);
3974
+ }
3975
+ finally { if (e_1) throw e_1.error; }
3976
+ }
3977
+ if (!isCommandAdded) {
3978
+ // Note: Only situation when this should happen is when pipeline has no tasks
3979
+ if ((newLines[newLines.length - 1] || '').startsWith('#')) {
3980
+ newLines.push('');
3981
+ }
3982
+ newLines.push("- ".concat(commandString));
3983
+ /*
3984
+ TODO: [🧠] Is this error relevant:
3985
+ throw new UnexpectedError(
3986
+ spaceTrim(
3987
+ (block) => `
3988
+ Can not add command to pipeline because there is no second heading in the pipeline
3989
+
3990
+ This should never happen because pipeline is deflated before adding command
3991
+
3992
+ The command to add:
3993
+ ${block(commandString)}
3994
+
3995
+ ---
3996
+ The original pipeline:
3997
+ ${block(pipelineString)}
3998
+
3999
+ ---
4000
+ Deflated pipeline:
4001
+ ${block(deflatedPipelineString)}
4002
+
4003
+ ---
4004
+ `,
4005
+ ),
4006
+ );
4007
+ */
4008
+ }
4009
+ return spaceTrim__default["default"](newLines.join('\n'));
4010
+ }
4011
+ /**
4012
+ * TODO: [🧠] What is the better solution - `- xxx`, - `- xxx` or preserve (see also next TODO)
4013
+ * TODO: When existing commands 1) as 2) number 3) list, add 4) new command as next number
4014
+ */
4015
+
4016
+ /**
4017
+ * Function `removePipelineCommand` will remove one command from pipeline string
4018
+ *
4019
+ * @public exported from `@promptbook/editable`
4020
+ */
4021
+ function removePipelineCommand(options) {
4022
+ var e_1, _a;
4023
+ var command = options.command, pipelineString = options.pipelineString;
4024
+ var lines = pipelineString.split('\n');
4025
+ // TODO: [🧽] DRY
4026
+ var currentType = 'MARKDOWN';
4027
+ var newLines = [];
4028
+ try {
4029
+ for (var lines_1 = __values(lines), lines_1_1 = lines_1.next(); !lines_1_1.done; lines_1_1 = lines_1.next()) {
4030
+ var line = lines_1_1.value;
4031
+ if (currentType === 'MARKDOWN') {
4032
+ if (line.startsWith('```')) {
4033
+ currentType = 'CODE_BLOCK';
4034
+ }
4035
+ else if (line.includes('<!--')) {
4036
+ currentType = 'COMMENT';
4037
+ }
4038
+ }
4039
+ else if (currentType === 'CODE_BLOCK') {
4040
+ if (line.startsWith('```')) {
4041
+ currentType = 'MARKDOWN';
4042
+ }
4043
+ }
4044
+ else if (currentType === 'COMMENT') {
4045
+ if (line.includes('-->')) {
4046
+ currentType = 'MARKDOWN';
4047
+ }
4048
+ }
4049
+ if (currentType === 'MARKDOWN' && /^(-|\d\))/m.test(line) && line.toUpperCase().includes(command)) {
4050
+ continue;
4051
+ }
4052
+ newLines.push(line);
4053
+ }
4054
+ }
4055
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
4056
+ finally {
4057
+ try {
4058
+ if (lines_1_1 && !lines_1_1.done && (_a = lines_1.return)) _a.call(lines_1);
4059
+ }
4060
+ finally { if (e_1) throw e_1.error; }
4061
+ }
4062
+ var newPipeline = spaceTrim__default["default"](newLines.join('\n'));
4063
+ return newPipeline;
4064
+ }
4065
+
4066
+ /**
4067
+ * This error indicates that the promptbook object has valid syntax (=can be parsed) but contains logical errors (like circular dependencies)
4068
+ *
4069
+ * @public exported from `@promptbook/core`
4070
+ */
4071
+ var PipelineLogicError = /** @class */ (function (_super) {
4072
+ __extends(PipelineLogicError, _super);
4073
+ function PipelineLogicError(message) {
4074
+ var _this = _super.call(this, message) || this;
4075
+ _this.name = 'PipelineLogicError';
4076
+ Object.setPrototypeOf(_this, PipelineLogicError.prototype);
4077
+ return _this;
4078
+ }
4079
+ return PipelineLogicError;
4080
+ }(Error));
4081
+
4082
+ /**
4083
+ * Function `renamePipelineParameter` will find all usable parameters for given task
4084
+ * In other words, it will find all parameters that are not used in the task itseld and all its dependencies
4085
+ *
4086
+ * @throws {PipelineLogicError} If the new parameter name is already used in the pipeline
4087
+ * @public exported from `@promptbook/editable`
4088
+ */
4089
+ function renamePipelineParameter(options) {
4090
+ var e_1, _a, e_2, _b;
4091
+ var pipeline = options.pipeline, oldParameterName = options.oldParameterName, newParameterName = options.newParameterName;
4092
+ if (pipeline.parameters.some(function (parameter) { return parameter.name === newParameterName; })) {
4093
+ throw new PipelineLogicError("Can not replace {".concat(oldParameterName, "} to {").concat(newParameterName, "} because {").concat(newParameterName, "} is already used in the pipeline"));
4094
+ }
4095
+ var renamedPipeline = __assign(__assign({}, pipeline), {
4096
+ // <- TODO: [🪓] This should be without `as $PipelineJson`
4097
+ parameters: __spreadArray([], __read(pipeline.parameters), false), tasks: __spreadArray([], __read(pipeline.tasks), false) });
4098
+ try {
4099
+ for (var _c = __values(renamedPipeline.parameters), _d = _c.next(); !_d.done; _d = _c.next()) {
4100
+ var parameter = _d.value;
4101
+ if (parameter.name !== oldParameterName) {
4102
+ continue;
4103
+ }
4104
+ parameter.name = newParameterName;
4105
+ }
4106
+ }
4107
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
4108
+ finally {
4109
+ try {
4110
+ if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
4111
+ }
4112
+ finally { if (e_1) throw e_1.error; }
4113
+ }
4114
+ try {
4115
+ for (var _e = __values(renamedPipeline.tasks), _f = _e.next(); !_f.done; _f = _e.next()) {
4116
+ var task = _f.value;
4117
+ if (task.resultingParameterName === oldParameterName) {
4118
+ task.resultingParameterName = newParameterName;
4119
+ }
4120
+ task.dependentParameterNames = task.dependentParameterNames.map(function (dependentParameterName) {
4121
+ return dependentParameterName === oldParameterName ? newParameterName : dependentParameterName;
4122
+ });
4123
+ task.content = task.content.replace(new RegExp("{".concat(oldParameterName, "}"), 'g'), "{".concat(newParameterName, "}"));
4124
+ task.title = task.title.replace(new RegExp("{".concat(oldParameterName, "}"), 'g'), "{".concat(newParameterName, "}"));
4125
+ task.description =
4126
+ task.description === undefined
4127
+ ? undefined
4128
+ : task.description.replace(new RegExp("{".concat(oldParameterName, "}"), 'g'), "{".concat(newParameterName, "}"));
4129
+ }
4130
+ }
4131
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
4132
+ finally {
4133
+ try {
4134
+ if (_f && !_f.done && (_b = _e.return)) _b.call(_e);
4135
+ }
4136
+ finally { if (e_2) throw e_2.error; }
4137
+ }
4138
+ return renamedPipeline;
4139
+ }
4140
+ /**
4141
+ * TODO: Also variant for `edit-pipeline-string`
4142
+ */
4143
+
576
4144
  // <- TODO: Auto convert to type `import { ... } from 'type-fest';`
577
4145
  /**
578
4146
  * Tests if the value is [🚉] serializable as JSON
@@ -635,10 +4203,32 @@
635
4203
  */
636
4204
 
637
4205
  exports.BOOK_LANGUAGE_VERSION = BOOK_LANGUAGE_VERSION;
4206
+ exports.COMMANDS = COMMANDS;
638
4207
  exports.PROMPTBOOK_ENGINE_VERSION = PROMPTBOOK_ENGINE_VERSION;
4208
+ exports.actionCommandParser = actionCommandParser;
4209
+ exports.addPipelineCommand = addPipelineCommand;
4210
+ exports.bookVersionCommandParser = bookVersionCommandParser;
4211
+ exports.deflatePipeline = deflatePipeline;
4212
+ exports.expectCommandParser = expectCommandParser;
4213
+ exports.foreachCommandParser = foreachCommandParser;
4214
+ exports.formatCommandParser = formatCommandParser;
4215
+ exports.formfactorCommandParser = formfactorCommandParser;
4216
+ exports.getParserForCommand = getParserForCommand;
4217
+ exports.instrumentCommandParser = instrumentCommandParser;
4218
+ exports.isFlatPipeline = isFlatPipeline;
4219
+ exports.jokerCommandParser = jokerCommandParser;
4220
+ exports.knowledgeCommandParser = knowledgeCommandParser;
4221
+ exports.knowledgeSourceContentToName = knowledgeSourceContentToName;
4222
+ exports.modelCommandParser = modelCommandParser;
4223
+ exports.parameterCommandParser = parameterCommandParser;
4224
+ exports.parseCommand = parseCommand;
4225
+ exports.personaCommandParser = personaCommandParser;
4226
+ exports.postprocessCommandParser = postprocessCommandParser;
639
4227
  exports.removePipelineCommand = removePipelineCommand;
640
4228
  exports.renamePipelineParameter = renamePipelineParameter;
4229
+ exports.sectionCommandParser = sectionCommandParser;
641
4230
  exports.stringifyPipelineJson = stringifyPipelineJson;
4231
+ exports.urlCommandParser = urlCommandParser;
642
4232
 
643
4233
  Object.defineProperty(exports, '__esModule', { value: true });
644
4234