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