@promptbook/node 0.78.4 → 0.80.0-0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/README.md +4 -0
  2. package/esm/index.es.js +866 -451
  3. package/esm/index.es.js.map +1 -1
  4. package/esm/typings/books/index.d.ts +6 -6
  5. package/esm/typings/src/_packages/core.index.d.ts +4 -2
  6. package/esm/typings/src/_packages/types.index.d.ts +10 -0
  7. package/esm/typings/src/_packages/utils.index.d.ts +4 -0
  8. package/esm/typings/src/cli/cli-commands/runInteractiveChatbot.d.ts +32 -0
  9. package/esm/typings/src/commands/_common/types/CommandParser.d.ts +5 -2
  10. package/esm/typings/src/config.d.ts +0 -25
  11. package/esm/typings/src/constants.d.ts +35 -0
  12. package/esm/typings/src/conversion/pipelineJsonToString.d.ts +1 -0
  13. package/esm/typings/src/conversion/pipelineStringToJsonSync.d.ts +1 -0
  14. package/esm/typings/src/formfactors/generator/GeneratorFormfactorDefinition.d.ts +6 -1
  15. package/esm/typings/src/formfactors/index.d.ts +12 -2
  16. package/esm/typings/src/formfactors/matcher/MatcherFormfactorDefinition.d.ts +6 -1
  17. package/esm/typings/src/high-level-abstractions/_common/HighLevelAbstraction.d.ts +20 -0
  18. package/esm/typings/src/high-level-abstractions/implicit-formfactor/ImplicitFormfactorHla.d.ts +10 -0
  19. package/esm/typings/src/high-level-abstractions/index.d.ts +44 -0
  20. package/esm/typings/src/high-level-abstractions/quick-chatbot/QuickChatbotHla.d.ts +10 -0
  21. package/esm/typings/src/llm-providers/remote/RemoteLlmExecutionTools.d.ts +1 -1
  22. package/esm/typings/src/llm-providers/remote/startRemoteServer.d.ts +1 -1
  23. package/esm/typings/src/prepare/prepareTasks.d.ts +1 -0
  24. package/esm/typings/src/types/typeAliases.d.ts +1 -1
  25. package/esm/typings/src/utils/normalization/orderJson.d.ts +21 -0
  26. package/esm/typings/src/utils/normalization/orderJson.test.d.ts +4 -0
  27. package/esm/typings/src/utils/organization/keepTypeImported.d.ts +9 -0
  28. package/esm/typings/src/utils/serialization/$deepFreeze.d.ts +1 -1
  29. package/esm/typings/src/utils/serialization/checkSerializableAsJson.d.ts +20 -2
  30. package/esm/typings/src/utils/serialization/deepClone.test.d.ts +1 -0
  31. package/esm/typings/src/utils/serialization/exportJson.d.ts +29 -0
  32. package/esm/typings/src/utils/serialization/isSerializableAsJson.d.ts +2 -1
  33. package/package.json +3 -2
  34. package/umd/index.umd.js +866 -451
  35. package/umd/index.umd.js.map +1 -1
  36. package/esm/typings/src/utils/serialization/$asDeeplyFrozenSerializableJson.d.ts +0 -17
package/umd/index.umd.js CHANGED
@@ -43,7 +43,7 @@
43
43
  *
44
44
  * @see https://github.com/webgptorg/promptbook
45
45
  */
46
- var PROMPTBOOK_ENGINE_VERSION = '0.78.3';
46
+ var PROMPTBOOK_ENGINE_VERSION = '0.79.0';
47
47
  /**
48
48
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
49
49
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -266,41 +266,6 @@
266
266
  * @public exported from `@promptbook/core`
267
267
  */
268
268
  var DEFAULT_PIPELINE_COLLECTION_BASE_FILENAME = "index";
269
- /**
270
- * Nonce which is used for replacing things in strings
271
- *
272
- * @private within the repository
273
- */
274
- var REPLACING_NONCE = 'u$k42k%!V2zo34w7Fu#@QUHYPW';
275
- /**
276
- * The names of the parameters that are reserved for special purposes
277
- *
278
- * @public exported from `@promptbook/core`
279
- */
280
- var RESERVED_PARAMETER_NAMES =
281
- /* !!!!!! $asDeeplyFrozenSerializableJson('RESERVED_PARAMETER_NAMES', _____ as const); */ [
282
- 'content',
283
- 'context',
284
- 'knowledge',
285
- 'examples',
286
- 'modelName',
287
- 'currentDate',
288
- // <- TODO: list here all command names
289
- // <- TODO: Add more like 'date', 'modelName',...
290
- // <- TODO: Add [emoji] + instructions ACRY when adding new reserved parameter
291
- ];
292
- /**
293
- * @@@
294
- *
295
- * @private within the repository
296
- */
297
- var RESERVED_PARAMETER_MISSING_VALUE = 'MISSING-' + REPLACING_NONCE;
298
- /**
299
- * @@@
300
- *
301
- * @private within the repository
302
- */
303
- var RESERVED_PARAMETER_RESTRICTED = 'RESTRICTED-' + REPLACING_NONCE;
304
269
  // <- TODO: [🧜‍♂️]
305
270
  /**
306
271
  * @@@
@@ -335,7 +300,6 @@
335
300
  // Note: In normal situations, we check the pipeline logic:
336
301
  true);
337
302
  /**
338
- * TODO: Extract `constants.ts` from `config.ts`
339
303
  * Note: [💞] Ignore a discrepancy between file name and entity name
340
304
  * TODO: [🧠][🧜‍♂️] Maybe join remoteUrl and path into single value
341
305
  */
@@ -386,6 +350,7 @@
386
350
  /**
387
351
  * Converts promptbook in JSON format to string format
388
352
  *
353
+ * @deprecated TODO: [🥍][🧠] Backup original files in `PipelineJson` same as in Promptbook.studio
389
354
  * @param pipelineJson Promptbook in JSON format (.book.json)
390
355
  * @returns Promptbook in string format (.book.md)
391
356
  * @public exported from `@promptbook/core`
@@ -589,6 +554,332 @@
589
554
  * TODO: [🧠] Should be in generated .book.md file GENERATOR_WARNING
590
555
  */
591
556
 
557
+ /**
558
+ * Orders JSON object by keys
559
+ *
560
+ * @returns The same type of object as the input re-ordered
561
+ * @public exported from `@promptbook/utils`
562
+ */
563
+ function orderJson(options) {
564
+ var value = options.value, order = options.order;
565
+ var orderedValue = __assign(__assign({}, (order === undefined ? {} : Object.fromEntries(order.map(function (key) { return [key, undefined]; })))), value);
566
+ return orderedValue;
567
+ }
568
+
569
+ /**
570
+ * Freezes the given object and all its nested objects recursively
571
+ *
572
+ * Note: `$` is used to indicate that this function is not a pure function - it mutates given object
573
+ * Note: This function mutates the object and returns the original (but mutated-deep-freezed) object
574
+ *
575
+ * @returns The same object as the input, but deeply frozen
576
+ * @public exported from `@promptbook/utils`
577
+ */
578
+ function $deepFreeze(objectValue) {
579
+ var e_1, _a;
580
+ if (Array.isArray(objectValue)) {
581
+ return Object.freeze(objectValue.map(function (item) { return $deepFreeze(item); }));
582
+ }
583
+ var propertyNames = Object.getOwnPropertyNames(objectValue);
584
+ try {
585
+ for (var propertyNames_1 = __values(propertyNames), propertyNames_1_1 = propertyNames_1.next(); !propertyNames_1_1.done; propertyNames_1_1 = propertyNames_1.next()) {
586
+ var propertyName = propertyNames_1_1.value;
587
+ var value = objectValue[propertyName];
588
+ if (value && typeof value === 'object') {
589
+ $deepFreeze(value);
590
+ }
591
+ }
592
+ }
593
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
594
+ finally {
595
+ try {
596
+ if (propertyNames_1_1 && !propertyNames_1_1.done && (_a = propertyNames_1.return)) _a.call(propertyNames_1);
597
+ }
598
+ finally { if (e_1) throw e_1.error; }
599
+ }
600
+ Object.freeze(objectValue);
601
+ return objectValue;
602
+ }
603
+ /**
604
+ * TODO: [🧠] Is there a way how to meaningfully test this utility
605
+ */
606
+
607
+ /**
608
+ * Make error report URL for the given error
609
+ *
610
+ * @private !!!!!!
611
+ */
612
+ function getErrorReportUrl(error) {
613
+ var report = {
614
+ title: "\uD83D\uDC1C Error report from ".concat(NAME),
615
+ body: spaceTrim__default["default"](function (block) { return "\n\n\n `".concat(error.name || 'Error', "` has occurred in the [").concat(NAME, "], please look into it @").concat(ADMIN_GITHUB_NAME, ".\n\n ```\n ").concat(block(error.message || '(no error message)'), "\n ```\n\n\n ## More info:\n\n - **Promptbook engine version:** ").concat(PROMPTBOOK_ENGINE_VERSION, "\n - **Book language version:** ").concat(BOOK_LANGUAGE_VERSION, "\n - **Time:** ").concat(new Date().toISOString(), "\n\n <details>\n <summary>Stack trace:</summary>\n\n ## Stack trace:\n\n ```stacktrace\n ").concat(block(error.stack || '(empty)'), "\n ```\n </details>\n\n "); }),
616
+ };
617
+ var reportUrl = new URL("https://github.com/webgptorg/promptbook/issues/new");
618
+ reportUrl.searchParams.set('labels', 'bug');
619
+ reportUrl.searchParams.set('assignees', ADMIN_GITHUB_NAME);
620
+ reportUrl.searchParams.set('title', report.title);
621
+ reportUrl.searchParams.set('body', report.body);
622
+ return reportUrl;
623
+ }
624
+
625
+ /**
626
+ * This error type indicates that the error should not happen and its last check before crashing with some other error
627
+ *
628
+ * @public exported from `@promptbook/core`
629
+ */
630
+ var UnexpectedError = /** @class */ (function (_super) {
631
+ __extends(UnexpectedError, _super);
632
+ function UnexpectedError(message) {
633
+ var _this = _super.call(this, spaceTrim.spaceTrim(function (block) { return "\n ".concat(block(message), "\n\n Note: This error should not happen.\n It's probbably a bug in the pipeline collection\n\n Please report issue:\n ").concat(block(getErrorReportUrl(new Error(message)).href), "\n\n Or contact us on ").concat(ADMIN_EMAIL, "\n\n "); })) || this;
634
+ _this.name = 'UnexpectedError';
635
+ Object.setPrototypeOf(_this, UnexpectedError.prototype);
636
+ return _this;
637
+ }
638
+ return UnexpectedError;
639
+ }(Error));
640
+
641
+ /**
642
+ * Checks if the value is [🚉] serializable as JSON
643
+ * If not, throws an UnexpectedError with a rich error message and tracking
644
+ *
645
+ * - Almost all primitives are serializable BUT:
646
+ * - `undefined` is not serializable
647
+ * - `NaN` is not serializable
648
+ * - Objects and arrays are serializable if all their properties are serializable
649
+ * - Functions are not serializable
650
+ * - Circular references are not serializable
651
+ * - `Date` objects are not serializable
652
+ * - `Map` and `Set` objects are not serializable
653
+ * - `RegExp` objects are not serializable
654
+ * - `Error` objects are not serializable
655
+ * - `Symbol` objects are not serializable
656
+ * - And much more...
657
+ *
658
+ * @throws UnexpectedError if the value is not serializable as JSON
659
+ * @public exported from `@promptbook/utils`
660
+ */
661
+ function checkSerializableAsJson(options) {
662
+ var e_1, _a;
663
+ var value = options.value, name = options.name, message = options.message;
664
+ if (value === undefined) {
665
+ throw new UnexpectedError("".concat(name, " is undefined"));
666
+ }
667
+ else if (value === null) {
668
+ return;
669
+ }
670
+ else if (typeof value === 'boolean') {
671
+ return;
672
+ }
673
+ else if (typeof value === 'number' && !isNaN(value)) {
674
+ return;
675
+ }
676
+ else if (typeof value === 'string') {
677
+ return;
678
+ }
679
+ else if (typeof value === 'symbol') {
680
+ throw new UnexpectedError("".concat(name, " is symbol"));
681
+ }
682
+ else if (typeof value === 'function') {
683
+ throw new UnexpectedError("".concat(name, " is function"));
684
+ }
685
+ else if (typeof value === 'object' && Array.isArray(value)) {
686
+ for (var i = 0; i < value.length; i++) {
687
+ checkSerializableAsJson({ name: "".concat(name, "[").concat(i, "]"), value: value[i], message: message });
688
+ }
689
+ }
690
+ else if (typeof value === 'object') {
691
+ if (value instanceof Date) {
692
+ 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 "); }));
693
+ }
694
+ else if (value instanceof Map) {
695
+ throw new UnexpectedError("".concat(name, " is Map"));
696
+ }
697
+ else if (value instanceof Set) {
698
+ throw new UnexpectedError("".concat(name, " is Set"));
699
+ }
700
+ else if (value instanceof RegExp) {
701
+ throw new UnexpectedError("".concat(name, " is RegExp"));
702
+ }
703
+ else if (value instanceof Error) {
704
+ 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 "); }));
705
+ }
706
+ else {
707
+ try {
708
+ for (var _b = __values(Object.entries(value)), _c = _b.next(); !_c.done; _c = _b.next()) {
709
+ var _d = __read(_c.value, 2), subName = _d[0], subValue = _d[1];
710
+ if (subValue === undefined) {
711
+ // Note: undefined in object is serializable - it is just omited
712
+ continue;
713
+ }
714
+ checkSerializableAsJson({ name: "".concat(name, ".").concat(subName), value: subValue, message: message });
715
+ }
716
+ }
717
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
718
+ finally {
719
+ try {
720
+ if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
721
+ }
722
+ finally { if (e_1) throw e_1.error; }
723
+ }
724
+ try {
725
+ JSON.stringify(value); // <- TODO: [0]
726
+ }
727
+ catch (error) {
728
+ if (!(error instanceof Error)) {
729
+ throw error;
730
+ }
731
+ throw new UnexpectedError(spaceTrim__default["default"](function (block) { return "\n `".concat(name, "` is not serializable\n\n ").concat(block(error.toString()), "\n\n Additional message for `").concat(name, "`:\n ").concat(block(message || '(nothing)'), "\n "); }));
732
+ }
733
+ /*
734
+ TODO: [0] Is there some more elegant way to check circular references?
735
+ const seen = new Set();
736
+ const stack = [{ value }];
737
+ while (stack.length > 0) {
738
+ const { value } = stack.pop()!;
739
+ if (typeof value === 'object' && value !== null) {
740
+ if (seen.has(value)) {
741
+ throw new UnexpectedError(`${name} has circular reference`);
742
+ }
743
+ seen.add(value);
744
+ if (Array.isArray(value)) {
745
+ stack.push(...value.map((value) => ({ value })));
746
+ } else {
747
+ stack.push(...Object.values(value).map((value) => ({ value })));
748
+ }
749
+ }
750
+ }
751
+ */
752
+ return;
753
+ }
754
+ }
755
+ else {
756
+ 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 "); }));
757
+ }
758
+ }
759
+ /**
760
+ * TODO: Can be return type more type-safe? like `asserts options.value is JsonValue`
761
+ * TODO: [🧠][main] !!! In-memory cache of same values to prevent multiple checks
762
+ * Note: [🐠] This is how `checkSerializableAsJson` + `isSerializableAsJson` together can just retun true/false or rich error message
763
+ */
764
+
765
+ /**
766
+ * @@@
767
+ *
768
+ * @public exported from `@promptbook/utils`
769
+ */
770
+ function deepClone(objectValue) {
771
+ return JSON.parse(JSON.stringify(objectValue));
772
+ /*
773
+ !!!!!!!!
774
+ TODO: [🧠] Is there a better implementation?
775
+ > const propertyNames = Object.getOwnPropertyNames(objectValue);
776
+ > for (const propertyName of propertyNames) {
777
+ > const value = (objectValue as really_any)[propertyName];
778
+ > if (value && typeof value === 'object') {
779
+ > deepClone(value);
780
+ > }
781
+ > }
782
+ > return Object.assign({}, objectValue);
783
+ */
784
+ }
785
+ /**
786
+ * TODO: [🧠] Is there a way how to meaningfully test this utility
787
+ */
788
+
789
+ /**
790
+ * Utility to export a JSON object from a function
791
+ *
792
+ * 1) Checks if the value is serializable as JSON
793
+ * 2) Makes a deep clone of the object
794
+ * 2) Orders the object properties
795
+ * 2) Deeply freezes the cloned object
796
+ *
797
+ * Note: This function does not mutates the given object
798
+ *
799
+ * @returns The same type of object as the input but read-only and re-ordered
800
+ * @public exported from `@promptbook/utils`
801
+ */
802
+ function exportJson(options) {
803
+ var name = options.name, value = options.value, order = options.order, message = options.message;
804
+ checkSerializableAsJson({ name: name, value: value, message: message });
805
+ var orderedValue =
806
+ // TODO: Fix error "Type instantiation is excessively deep and possibly infinite."
807
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
808
+ // @ts-ignore
809
+ order === undefined
810
+ ? deepClone(value)
811
+ : orderJson({
812
+ value: value,
813
+ // <- Note: checkSerializableAsJson asserts that the value is serializable as JSON
814
+ order: order,
815
+ });
816
+ $deepFreeze(orderedValue);
817
+ return orderedValue;
818
+ }
819
+ /**
820
+ * TODO: [🧠] Is there a way how to meaningfully test this utility
821
+ */
822
+
823
+ /**
824
+ * Order of keys in the pipeline JSON
825
+ *
826
+ * @public exported from `@promptbook/core`
827
+ */
828
+ var ORDER_OF_PIPELINE_JSON = [
829
+ 'title',
830
+ 'pipelineUrl',
831
+ 'bookVersion',
832
+ 'description',
833
+ 'formfactorName',
834
+ 'parameters',
835
+ 'tasks',
836
+ 'personas',
837
+ 'preparations',
838
+ 'knowledgeSources',
839
+ 'knowledgePieces',
840
+ ];
841
+ /**
842
+ * Nonce which is used for replacing things in strings
843
+ *
844
+ * @private within the repository
845
+ */
846
+ var REPLACING_NONCE = 'u$k42k%!V2zo34w7Fu#@QUHYPW';
847
+ /**
848
+ * @@@
849
+ *
850
+ * @private within the repository
851
+ */
852
+ var RESERVED_PARAMETER_MISSING_VALUE = 'MISSING-' + REPLACING_NONCE;
853
+ /**
854
+ * @@@
855
+ *
856
+ * @private within the repository
857
+ */
858
+ var RESERVED_PARAMETER_RESTRICTED = 'RESTRICTED-' + REPLACING_NONCE;
859
+ /**
860
+ * The names of the parameters that are reserved for special purposes
861
+ *
862
+ * @public exported from `@promptbook/core`
863
+ */
864
+ var RESERVED_PARAMETER_NAMES = exportJson({
865
+ name: 'RESERVED_PARAMETER_NAMES',
866
+ message: "The names of the parameters that are reserved for special purposes",
867
+ value: [
868
+ 'content',
869
+ 'context',
870
+ 'knowledge',
871
+ 'examples',
872
+ 'modelName',
873
+ 'currentDate',
874
+ // <- TODO: list here all command names
875
+ // <- TODO: Add more like 'date', 'modelName',...
876
+ // <- TODO: Add [emoji] + instructions ACRY when adding new reserved parameter
877
+ ],
878
+ });
879
+ /**
880
+ * Note: [💞] Ignore a discrepancy between file name and entity name
881
+ */
882
+
592
883
  /**
593
884
  * This error type indicates that some tools are missing for pipeline execution or preparation
594
885
  *
@@ -672,48 +963,14 @@
672
963
  }
673
964
  finally { if (e_1) throw e_1.error; }
674
965
  return [7 /*endfinally*/];
675
- case 8: return [4 /*yield*/, Promise.all(tasks)];
676
- case 9:
677
- _e.sent();
678
- return [2 /*return*/];
679
- }
680
- });
681
- });
682
- }
683
-
684
- /**
685
- * @@@
686
- *
687
- * Note: `$` is used to indicate that this function is not a pure function - it mutates given object
688
- * Note: This function mutates the object and returns the original (but mutated-deep-freezed) object
689
- *
690
- * @returns The same object as the input, but deeply frozen
691
- * @public exported from `@promptbook/utils`
692
- */
693
- function $deepFreeze(objectValue) {
694
- var e_1, _a;
695
- var propertyNames = Object.getOwnPropertyNames(objectValue);
696
- try {
697
- for (var propertyNames_1 = __values(propertyNames), propertyNames_1_1 = propertyNames_1.next(); !propertyNames_1_1.done; propertyNames_1_1 = propertyNames_1.next()) {
698
- var propertyName = propertyNames_1_1.value;
699
- var value = objectValue[propertyName];
700
- if (value && typeof value === 'object') {
701
- $deepFreeze(value);
702
- }
703
- }
704
- }
705
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
706
- finally {
707
- try {
708
- if (propertyNames_1_1 && !propertyNames_1_1.done && (_a = propertyNames_1.return)) _a.call(propertyNames_1);
709
- }
710
- finally { if (e_1) throw e_1.error; }
711
- }
712
- return Object.freeze(objectValue);
966
+ case 8: return [4 /*yield*/, Promise.all(tasks)];
967
+ case 9:
968
+ _e.sent();
969
+ return [2 /*return*/];
970
+ }
971
+ });
972
+ });
713
973
  }
714
- /**
715
- * TODO: [🧠] Is there a way how to meaningfully test this utility
716
- */
717
974
 
718
975
  /**
719
976
  * Represents the usage with no resources consumed
@@ -771,29 +1028,6 @@
771
1028
  * Note: [💞] Ignore a discrepancy between file name and entity name
772
1029
  */
773
1030
 
774
- /**
775
- * @@@
776
- *
777
- * @public exported from `@promptbook/utils`
778
- */
779
- function deepClone(objectValue) {
780
- return JSON.parse(JSON.stringify(objectValue));
781
- /*
782
- TODO: [🧠] Is there a better implementation?
783
- > const propertyNames = Object.getOwnPropertyNames(objectValue);
784
- > for (const propertyName of propertyNames) {
785
- > const value = (objectValue as really_any)[propertyName];
786
- > if (value && typeof value === 'object') {
787
- > deepClone(value);
788
- > }
789
- > }
790
- > return Object.assign({}, objectValue);
791
- */
792
- }
793
- /**
794
- * TODO: [🧠] Is there a way how to meaningfully test this utility
795
- */
796
-
797
1031
  /**
798
1032
  * Function `addUsage` will add multiple usages into one
799
1033
  *
@@ -969,40 +1203,6 @@
969
1203
  return PipelineExecutionError;
970
1204
  }(Error));
971
1205
 
972
- /**
973
- * Make error report URL for the given error
974
- *
975
- * @private !!!!!!
976
- */
977
- function getErrorReportUrl(error) {
978
- var report = {
979
- title: "\uD83D\uDC1C Error report from ".concat(NAME),
980
- body: spaceTrim__default["default"](function (block) { return "\n\n\n `".concat(error.name || 'Error', "` has occurred in the [").concat(NAME, "], please look into it @").concat(ADMIN_GITHUB_NAME, ".\n\n ```\n ").concat(block(error.message || '(no error message)'), "\n ```\n\n\n ## More info:\n\n - **Promptbook engine version:** ").concat(PROMPTBOOK_ENGINE_VERSION, "\n - **Book language version:** ").concat(BOOK_LANGUAGE_VERSION, "\n - **Time:** ").concat(new Date().toISOString(), "\n\n <details>\n <summary>Stack trace:</summary>\n\n ## Stack trace:\n\n ```stacktrace\n ").concat(block(error.stack || '(empty)'), "\n ```\n </details>\n\n "); }),
981
- };
982
- var reportUrl = new URL("https://github.com/webgptorg/promptbook/issues/new");
983
- reportUrl.searchParams.set('labels', 'bug');
984
- reportUrl.searchParams.set('assignees', ADMIN_GITHUB_NAME);
985
- reportUrl.searchParams.set('title', report.title);
986
- reportUrl.searchParams.set('body', report.body);
987
- return reportUrl;
988
- }
989
-
990
- /**
991
- * This error type indicates that the error should not happen and its last check before crashing with some other error
992
- *
993
- * @public exported from `@promptbook/core`
994
- */
995
- var UnexpectedError = /** @class */ (function (_super) {
996
- __extends(UnexpectedError, _super);
997
- function UnexpectedError(message) {
998
- var _this = _super.call(this, spaceTrim.spaceTrim(function (block) { return "\n ".concat(block(message), "\n\n Note: This error should not happen.\n It's probbably a bug in the pipeline collection\n\n Please report issue:\n ").concat(block(getErrorReportUrl(new Error(message)).href), "\n\n Or contact us on ").concat(ADMIN_EMAIL, "\n\n "); })) || this;
999
- _this.name = 'UnexpectedError';
1000
- Object.setPrototypeOf(_this, UnexpectedError.prototype);
1001
- return _this;
1002
- }
1003
- return UnexpectedError;
1004
- }(Error));
1005
-
1006
1206
  /**
1007
1207
  * Multiple LLM Execution Tools is a proxy server that uses multiple execution tools internally and exposes the executor interface externally.
1008
1208
  *
@@ -1295,7 +1495,7 @@
1295
1495
  * TODO: [👷‍♂️] @@@ Manual about construction of llmTools
1296
1496
  */
1297
1497
 
1298
- var PipelineCollection = [{title:"Prepare Knowledge from Markdown",pipelineUrl:"https://promptbook.studio/promptbook/prepare-knowledge-from-markdown.book.md",formfactorName:"GENERIC",parameters:[{name:"knowledgeContent",description:"Markdown document content",isInput:true,isOutput:false},{name:"knowledgePieces",description:"The knowledge JSON object",isInput:false,isOutput:true}],tasks:[{taskType:"PROMPT_TASK",name:"knowledge",title:"Knowledge",content:"You are experienced data researcher, extract the important knowledge from the document.\n\n# Rules\n\n- Make pieces of information concise, clear, and easy to understand\n- One piece of information should be approximately 1 paragraph\n- Divide the paragraphs by markdown horizontal lines ---\n- Omit irrelevant information\n- Group redundant information\n- Write just extracted information, nothing else\n\n# The document\n\nTake information from this document:\n\n> {knowledgeContent}",resultingParameterName:"knowledgePieces",dependentParameterNames:["knowledgeContent"]}],knowledgeSources:[],knowledgePieces:[],personas:[],preparations:[],sourceFile:"./books/prepare-knowledge-from-markdown.book.md"},{title:"Prepare Keywords",pipelineUrl:"https://promptbook.studio/promptbook/prepare-knowledge-keywords.book.md",formfactorName:"GENERIC",parameters:[{name:"knowledgePieceContent",description:"The content",isInput:true,isOutput:false},{name:"keywords",description:"Keywords separated by comma",isInput:false,isOutput:true}],tasks:[{taskType:"PROMPT_TASK",name:"knowledge",title:"Knowledge",content:"You are experienced data researcher, detect the important keywords in the document.\n\n# Rules\n\n- Write just keywords separated by comma\n\n# The document\n\nTake information from this document:\n\n> {knowledgePieceContent}",resultingParameterName:"keywords",dependentParameterNames:["knowledgePieceContent"]}],knowledgeSources:[],knowledgePieces:[],personas:[],preparations:[],sourceFile:"./books/prepare-knowledge-keywords.book.md"},{title:"Prepare Title",pipelineUrl:"https://promptbook.studio/promptbook/prepare-knowledge-title.book.md",formfactorName:"GENERIC",parameters:[{name:"knowledgePieceContent",description:"The content",isInput:true,isOutput:false},{name:"title",description:"The title of the document",isInput:false,isOutput:true}],tasks:[{taskType:"PROMPT_TASK",name:"knowledge",title:"Knowledge",content:"You are experienced content creator, write best title for the document.\n\n# Rules\n\n- Write just title, nothing else\n- Title should be concise and clear\n- Write maximum 5 words for the title\n\n# The document\n\n> {knowledgePieceContent}",resultingParameterName:"title",expectations:{words:{min:1,max:8}},dependentParameterNames:["knowledgePieceContent"]}],knowledgeSources:[],knowledgePieces:[],personas:[],preparations:[],sourceFile:"./books/prepare-knowledge-title.book.md"},{title:"Prepare Keywords",pipelineUrl:"https://promptbook.studio/promptbook/prepare-persona.book.md",formfactorName:"GENERIC",parameters:[{name:"availableModelNames",description:"List of available model names separated by comma (,)",isInput:true,isOutput:false},{name:"personaDescription",description:"Description of the persona",isInput:true,isOutput:false},{name:"modelRequirements",description:"Specific requirements for the model",isInput:false,isOutput:true}],tasks:[{taskType:"PROMPT_TASK",name:"make-model-requirements",title:"Make modelRequirements",content:"You are experienced AI engineer, you need to create virtual assistant.\nWrite\n\n## Example\n\n```json\n{\n\"modelName\": \"gpt-4o\",\n\"systemMessage\": \"You are experienced AI engineer and helpfull assistant.\",\n\"temperature\": 0.7\n}\n```\n\n## Instructions\n\n- Your output format is JSON object\n- Write just the JSON object, no other text should be present\n- It contains the following keys:\n - `modelName`: The name of the model to use\n - `systemMessage`: The system message to provide context to the model\n - `temperature`: The sampling temperature to use\n\n### Key `modelName`\n\nPick from the following models:\n\n- {availableModelNames}\n\n### Key `systemMessage`\n\nThe system message is used to communicate instructions or provide context to the model at the beginning of a conversation. It is displayed in a different format compared to user messages, helping the model understand its role in the conversation. The system message typically guides the model's behavior, sets the tone, or specifies desired output from the model. By utilizing the system message effectively, users can steer the model towards generating more accurate and relevant responses.\n\nFor example:\n\n> You are an experienced AI engineer and helpful assistant.\n\n> You are a friendly and knowledgeable chatbot.\n\n### Key `temperature`\n\nThe sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, the model will use log probability to automatically increase the temperature until certain thresholds are hit.\n\nYou can pick a value between 0 and 2. For example:\n\n- `0.1`: Low temperature, extremely conservative and deterministic\n- `0.5`: Medium temperature, balanced between conservative and creative\n- `1.0`: High temperature, creative and bit random\n- `1.5`: Very high temperature, extremely creative and often chaotic and unpredictable\n- `2.0`: Maximum temperature, completely random and unpredictable, for some extreme creative use cases\n\n# The assistant\n\nTake this description of the persona:\n\n> {personaDescription}",resultingParameterName:"modelRequirements",format:"JSON",dependentParameterNames:["availableModelNames","personaDescription"]}],knowledgeSources:[],knowledgePieces:[],personas:[],preparations:[],sourceFile:"./books/prepare-persona.book.md"}];
1498
+ var PipelineCollection = [{title:"Prepare Knowledge from Markdown",pipelineUrl:"https://promptbook.studio/promptbook/prepare-knowledge-from-markdown.book.md",formfactorName:"GENERIC",parameters:[{name:"knowledgeContent",description:"Markdown document content",isInput:true,isOutput:false},{name:"knowledgePieces",description:"The knowledge JSON object",isInput:false,isOutput:true}],tasks:[{taskType:"PROMPT_TASK",name:"knowledge",title:"Knowledge",content:"You are experienced data researcher, extract the important knowledge from the document.\n\n# Rules\n\n- Make pieces of information concise, clear, and easy to understand\n- One piece of information should be approximately 1 paragraph\n- Divide the paragraphs by markdown horizontal lines ---\n- Omit irrelevant information\n- Group redundant information\n- Write just extracted information, nothing else\n\n# The document\n\nTake information from this document:\n\n> {knowledgeContent}",resultingParameterName:"knowledgePieces",dependentParameterNames:["knowledgeContent"]}],personas:[],preparations:[],knowledgeSources:[],knowledgePieces:[],sourceFile:"./books/prepare-knowledge-from-markdown.book.md"},{title:"Prepare Keywords",pipelineUrl:"https://promptbook.studio/promptbook/prepare-knowledge-keywords.book.md",formfactorName:"GENERIC",parameters:[{name:"knowledgePieceContent",description:"The content",isInput:true,isOutput:false},{name:"keywords",description:"Keywords separated by comma",isInput:false,isOutput:true}],tasks:[{taskType:"PROMPT_TASK",name:"knowledge",title:"Knowledge",content:"You are experienced data researcher, detect the important keywords in the document.\n\n# Rules\n\n- Write just keywords separated by comma\n\n# The document\n\nTake information from this document:\n\n> {knowledgePieceContent}",resultingParameterName:"keywords",dependentParameterNames:["knowledgePieceContent"]}],personas:[],preparations:[],knowledgeSources:[],knowledgePieces:[],sourceFile:"./books/prepare-knowledge-keywords.book.md"},{title:"Prepare Title",pipelineUrl:"https://promptbook.studio/promptbook/prepare-knowledge-title.book.md",formfactorName:"GENERIC",parameters:[{name:"knowledgePieceContent",description:"The content",isInput:true,isOutput:false},{name:"title",description:"The title of the document",isInput:false,isOutput:true}],tasks:[{taskType:"PROMPT_TASK",name:"knowledge",title:"Knowledge",content:"You are experienced content creator, write best title for the document.\n\n# Rules\n\n- Write just title, nothing else\n- Title should be concise and clear\n- Write maximum 5 words for the title\n\n# The document\n\n> {knowledgePieceContent}",resultingParameterName:"title",expectations:{words:{min:1,max:8}},dependentParameterNames:["knowledgePieceContent"]}],personas:[],preparations:[],knowledgeSources:[],knowledgePieces:[],sourceFile:"./books/prepare-knowledge-title.book.md"},{title:"Prepare Keywords",pipelineUrl:"https://promptbook.studio/promptbook/prepare-persona.book.md",formfactorName:"GENERIC",parameters:[{name:"availableModelNames",description:"List of available model names separated by comma (,)",isInput:true,isOutput:false},{name:"personaDescription",description:"Description of the persona",isInput:true,isOutput:false},{name:"modelRequirements",description:"Specific requirements for the model",isInput:false,isOutput:true}],tasks:[{taskType:"PROMPT_TASK",name:"make-model-requirements",title:"Make modelRequirements",content:"You are experienced AI engineer, you need to create virtual assistant.\nWrite\n\n## Example\n\n```json\n{\n\"modelName\": \"gpt-4o\",\n\"systemMessage\": \"You are experienced AI engineer and helpfull assistant.\",\n\"temperature\": 0.7\n}\n```\n\n## Instructions\n\n- Your output format is JSON object\n- Write just the JSON object, no other text should be present\n- It contains the following keys:\n - `modelName`: The name of the model to use\n - `systemMessage`: The system message to provide context to the model\n - `temperature`: The sampling temperature to use\n\n### Key `modelName`\n\nPick from the following models:\n\n- {availableModelNames}\n\n### Key `systemMessage`\n\nThe system message is used to communicate instructions or provide context to the model at the beginning of a conversation. It is displayed in a different format compared to user messages, helping the model understand its role in the conversation. The system message typically guides the model's behavior, sets the tone, or specifies desired output from the model. By utilizing the system message effectively, users can steer the model towards generating more accurate and relevant responses.\n\nFor example:\n\n> You are an experienced AI engineer and helpful assistant.\n\n> You are a friendly and knowledgeable chatbot.\n\n### Key `temperature`\n\nThe sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, the model will use log probability to automatically increase the temperature until certain thresholds are hit.\n\nYou can pick a value between 0 and 2. For example:\n\n- `0.1`: Low temperature, extremely conservative and deterministic\n- `0.5`: Medium temperature, balanced between conservative and creative\n- `1.0`: High temperature, creative and bit random\n- `1.5`: Very high temperature, extremely creative and often chaotic and unpredictable\n- `2.0`: Maximum temperature, completely random and unpredictable, for some extreme creative use cases\n\n# The assistant\n\nTake this description of the persona:\n\n> {personaDescription}",resultingParameterName:"modelRequirements",format:"JSON",dependentParameterNames:["availableModelNames","personaDescription"]}],personas:[],preparations:[],knowledgeSources:[],knowledgePieces:[],sourceFile:"./books/prepare-persona.book.md"}];
1299
1499
 
1300
1500
  /**
1301
1501
  * This error indicates that the promptbook in a markdown format cannot be parsed into a valid promptbook object
@@ -1569,6 +1769,21 @@
1569
1769
  }
1570
1770
  };
1571
1771
  try {
1772
+ /*
1773
+ TODO: [🧠][🅾] Should be empty pipeline valid or not
1774
+ // Note: Check that pipeline has some tasks
1775
+ if (pipeline.tasks.length === 0) {
1776
+ throw new PipelineLogicError(
1777
+ spaceTrim(
1778
+ (block) => `
1779
+ Pipeline must have at least one task
1780
+
1781
+ ${block(pipelineIdentification)}
1782
+ `,
1783
+ ),
1784
+ );
1785
+ }
1786
+ */
1572
1787
  // Note: Check each parameter individually
1573
1788
  for (var _d = __values(pipeline.parameters), _e = _d.next(); !_e.done; _e = _d.next()) {
1574
1789
  var parameter = _e.value;
@@ -1729,6 +1944,9 @@
1729
1944
  while (unresovedTasks.length > 0) {
1730
1945
  _loop_3();
1731
1946
  }
1947
+ // Note: Check that formfactor is corresponding to the pipeline interface
1948
+ // TODO: !!!!!! Implement this
1949
+ // pipeline.formfactorName
1732
1950
  }
1733
1951
  /**
1734
1952
  * TODO: !! [🧞‍♀️] Do not allow joker + foreach
@@ -1745,215 +1963,72 @@
1745
1963
  /**
1746
1964
  * TODO: [🧳][main] !!!! Validate that all examples match expectations
1747
1965
  * TODO: [🧳][🐝][main] !!!! Validate that knowledge is valid (non-void)
1748
- * TODO: [🧳][main] !!!! Validate that persona can be used only with CHAT variant
1749
- * TODO: [🧳][main] !!!! Validate that parameter with reserved name not used RESERVED_PARAMETER_NAMES
1750
- * TODO: [🧳][main] !!!! Validate that reserved parameter is not used as joker
1751
- * TODO: [🧠] Validation not only logic itself but imports around - files and websites and rerefenced pipelines exists
1752
- * TODO: [🛠] Actions, instruments (and maybe knowledge) => Functions and tools
1753
- */
1754
-
1755
- /**
1756
- * This error indicates that promptbook not found in the collection
1757
- *
1758
- * @public exported from `@promptbook/core`
1759
- */
1760
- var NotFoundError = /** @class */ (function (_super) {
1761
- __extends(NotFoundError, _super);
1762
- function NotFoundError(message) {
1763
- var _this = _super.call(this, message) || this;
1764
- _this.name = 'NotFoundError';
1765
- Object.setPrototypeOf(_this, NotFoundError.prototype);
1766
- return _this;
1767
- }
1768
- return NotFoundError;
1769
- }(Error));
1770
-
1771
- /**
1772
- * This error indicates errors in referencing promptbooks between each other
1773
- *
1774
- * @public exported from `@promptbook/core`
1775
- */
1776
- var PipelineUrlError = /** @class */ (function (_super) {
1777
- __extends(PipelineUrlError, _super);
1778
- function PipelineUrlError(message) {
1779
- var _this = _super.call(this, message) || this;
1780
- _this.name = 'PipelineUrlError';
1781
- Object.setPrototypeOf(_this, PipelineUrlError.prototype);
1782
- return _this;
1783
- }
1784
- return PipelineUrlError;
1785
- }(Error));
1786
-
1787
- /**
1788
- * Parses the task and returns the list of all parameter names
1789
- *
1790
- * @param template the string template with parameters in {curly} braces
1791
- * @returns the list of parameter names
1792
- * @public exported from `@promptbook/utils`
1793
- */
1794
- function extractParameterNames(template) {
1795
- var e_1, _a;
1796
- var matches = template.matchAll(/{\w+}/g);
1797
- var parameterNames = new Set();
1798
- try {
1799
- for (var matches_1 = __values(matches), matches_1_1 = matches_1.next(); !matches_1_1.done; matches_1_1 = matches_1.next()) {
1800
- var match = matches_1_1.value;
1801
- var parameterName = match[0].slice(1, -1);
1802
- parameterNames.add(parameterName);
1803
- }
1804
- }
1805
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
1806
- finally {
1807
- try {
1808
- if (matches_1_1 && !matches_1_1.done && (_a = matches_1.return)) _a.call(matches_1);
1809
- }
1810
- finally { if (e_1) throw e_1.error; }
1811
- }
1812
- return parameterNames;
1813
- }
1814
-
1815
- /**
1816
- * Checks if the value is [🚉] serializable as JSON
1817
- * If not, throws an UnexpectedError with a rich error message and tracking
1818
- *
1819
- * - Almost all primitives are serializable BUT:
1820
- * - `undefined` is not serializable
1821
- * - `NaN` is not serializable
1822
- * - Objects and arrays are serializable if all their properties are serializable
1823
- * - Functions are not serializable
1824
- * - Circular references are not serializable
1825
- * - `Date` objects are not serializable
1826
- * - `Map` and `Set` objects are not serializable
1827
- * - `RegExp` objects are not serializable
1828
- * - `Error` objects are not serializable
1829
- * - `Symbol` objects are not serializable
1830
- * - And much more...
1831
- *
1832
- * @throws UnexpectedError if the value is not serializable as JSON
1833
- * @public exported from `@promptbook/utils`
1834
- */
1835
- function checkSerializableAsJson(name, value) {
1836
- var e_1, _a;
1837
- if (value === undefined) {
1838
- throw new UnexpectedError("".concat(name, " is undefined"));
1839
- }
1840
- else if (value === null) {
1841
- return;
1842
- }
1843
- else if (typeof value === 'boolean') {
1844
- return;
1845
- }
1846
- else if (typeof value === 'number' && !isNaN(value)) {
1847
- return;
1848
- }
1849
- else if (typeof value === 'string') {
1850
- return;
1851
- }
1852
- else if (typeof value === 'symbol') {
1853
- throw new UnexpectedError("".concat(name, " is symbol"));
1854
- }
1855
- else if (typeof value === 'function') {
1856
- throw new UnexpectedError("".concat(name, " is function"));
1857
- }
1858
- else if (typeof value === 'object' && Array.isArray(value)) {
1859
- for (var i = 0; i < value.length; i++) {
1860
- checkSerializableAsJson("".concat(name, "[").concat(i, "]"), value[i]);
1861
- }
1862
- }
1863
- else if (typeof value === 'object') {
1864
- if (value instanceof Date) {
1865
- throw new UnexpectedError(spaceTrim__default["default"]("\n ".concat(name, " is Date\n\n Use `string_date_iso8601` instead\n ")));
1866
- }
1867
- else if (value instanceof Map) {
1868
- throw new UnexpectedError("".concat(name, " is Map"));
1869
- }
1870
- else if (value instanceof Set) {
1871
- throw new UnexpectedError("".concat(name, " is Set"));
1872
- }
1873
- else if (value instanceof RegExp) {
1874
- throw new UnexpectedError("".concat(name, " is RegExp"));
1875
- }
1876
- else if (value instanceof Error) {
1877
- throw new UnexpectedError(spaceTrim__default["default"]("\n ".concat(name, " is unserialized Error\n\n Use function `serializeError`\n ")));
1878
- }
1879
- else {
1880
- try {
1881
- for (var _b = __values(Object.entries(value)), _c = _b.next(); !_c.done; _c = _b.next()) {
1882
- var _d = __read(_c.value, 2), subName = _d[0], subValue = _d[1];
1883
- if (subValue === undefined) {
1884
- // Note: undefined in object is serializable - it is just omited
1885
- continue;
1886
- }
1887
- checkSerializableAsJson("".concat(name, ".").concat(subName), subValue);
1888
- }
1889
- }
1890
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
1891
- finally {
1892
- try {
1893
- if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
1894
- }
1895
- finally { if (e_1) throw e_1.error; }
1896
- }
1897
- try {
1898
- JSON.stringify(value); // <- TODO: [0]
1899
- }
1900
- catch (error) {
1901
- if (!(error instanceof Error)) {
1902
- throw error;
1903
- }
1904
- throw new UnexpectedError(spaceTrim__default["default"](function (block) { return "\n ".concat(name, " is not serializable\n\n ").concat(block(error.toString()), "\n "); }));
1905
- }
1906
- /*
1907
- TODO: [0] Is there some more elegant way to check circular references?
1908
- const seen = new Set();
1909
- const stack = [{ value }];
1910
- while (stack.length > 0) {
1911
- const { value } = stack.pop()!;
1912
- if (typeof value === 'object' && value !== null) {
1913
- if (seen.has(value)) {
1914
- throw new UnexpectedError(`${name} has circular reference`);
1915
- }
1916
- seen.add(value);
1917
- if (Array.isArray(value)) {
1918
- stack.push(...value.map((value) => ({ value })));
1919
- } else {
1920
- stack.push(...Object.values(value).map((value) => ({ value })));
1921
- }
1922
- }
1923
- }
1924
- */
1925
- return;
1926
- }
1927
- }
1928
- else {
1929
- throw new UnexpectedError("".concat(name, " is unknown"));
1930
- }
1931
- }
1932
- /**
1933
- * TODO: [🧠][🛣] More elegant way to tracking than passing `name`
1934
- * TODO: [🧠][main] !!! In-memory cache of same values to prevent multiple checks
1935
- * Note: [🐠] This is how `checkSerializableAsJson` + `isSerializableAsJson` together can just retun true/false or rich error message
1966
+ * TODO: [🧳][main] !!!! Validate that persona can be used only with CHAT variant
1967
+ * TODO: [🧳][main] !!!! Validate that parameter with reserved name not used RESERVED_PARAMETER_NAMES
1968
+ * TODO: [🧳][main] !!!! Validate that reserved parameter is not used as joker
1969
+ * TODO: [🧠] Validation not only logic itself but imports around - files and websites and rerefenced pipelines exists
1970
+ * TODO: [🛠] Actions, instruments (and maybe knowledge) => Functions and tools
1936
1971
  */
1937
1972
 
1938
1973
  /**
1939
- * @@@
1940
- * @@@
1974
+ * This error indicates that promptbook not found in the collection
1941
1975
  *
1942
- * Note: This function mutates the object and returns the original (but mutated-deep-freezed) object
1976
+ * @public exported from `@promptbook/core`
1977
+ */
1978
+ var NotFoundError = /** @class */ (function (_super) {
1979
+ __extends(NotFoundError, _super);
1980
+ function NotFoundError(message) {
1981
+ var _this = _super.call(this, message) || this;
1982
+ _this.name = 'NotFoundError';
1983
+ Object.setPrototypeOf(_this, NotFoundError.prototype);
1984
+ return _this;
1985
+ }
1986
+ return NotFoundError;
1987
+ }(Error));
1988
+
1989
+ /**
1990
+ * This error indicates errors in referencing promptbooks between each other
1943
1991
  *
1944
- * @param name - Name of the object for debugging purposes
1945
- * @param objectValue - Object to be deeply frozen
1946
- * @returns The same object as the input, but deeply frozen
1947
- * @private this is in comparison to `deepFreeze` a more specific utility and maybe not very good practice to use without specific reason and considerations
1992
+ * @public exported from `@promptbook/core`
1948
1993
  */
1949
- function $asDeeplyFrozenSerializableJson(name, objectValue) {
1950
- checkSerializableAsJson(name, objectValue);
1951
- return $deepFreeze(objectValue);
1952
- }
1994
+ var PipelineUrlError = /** @class */ (function (_super) {
1995
+ __extends(PipelineUrlError, _super);
1996
+ function PipelineUrlError(message) {
1997
+ var _this = _super.call(this, message) || this;
1998
+ _this.name = 'PipelineUrlError';
1999
+ Object.setPrototypeOf(_this, PipelineUrlError.prototype);
2000
+ return _this;
2001
+ }
2002
+ return PipelineUrlError;
2003
+ }(Error));
2004
+
1953
2005
  /**
1954
- * TODO: [🧠][🛣] More elegant way to tracking than passing `name`
1955
- * TODO: [🧠] Is there a way how to meaningfully test this utility
2006
+ * Parses the task and returns the list of all parameter names
2007
+ *
2008
+ * @param template the string template with parameters in {curly} braces
2009
+ * @returns the list of parameter names
2010
+ * @public exported from `@promptbook/utils`
1956
2011
  */
2012
+ function extractParameterNames(template) {
2013
+ var e_1, _a;
2014
+ var matches = template.matchAll(/{\w+}/g);
2015
+ var parameterNames = new Set();
2016
+ try {
2017
+ for (var matches_1 = __values(matches), matches_1_1 = matches_1.next(); !matches_1_1.done; matches_1_1 = matches_1.next()) {
2018
+ var match = matches_1_1.value;
2019
+ var parameterName = match[0].slice(1, -1);
2020
+ parameterNames.add(parameterName);
2021
+ }
2022
+ }
2023
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
2024
+ finally {
2025
+ try {
2026
+ if (matches_1_1 && !matches_1_1.done && (_a = matches_1.return)) _a.call(matches_1);
2027
+ }
2028
+ finally { if (e_1) throw e_1.error; }
2029
+ }
2030
+ return parameterNames;
2031
+ }
1957
2032
 
1958
2033
  /**
1959
2034
  * Unprepare just strips the preparation data of the pipeline
@@ -1972,7 +2047,12 @@
1972
2047
  delete taskUnprepared.preparedContent;
1973
2048
  return taskUnprepared;
1974
2049
  });
1975
- return $asDeeplyFrozenSerializableJson('Unprepared PipelineJson', __assign(__assign({}, pipeline), { tasks: tasks, knowledgeSources: knowledgeSources, knowledgePieces: [], personas: personas, preparations: [] }));
2050
+ return exportJson({
2051
+ name: 'pipelineJson',
2052
+ message: "Result of `unpreparePipeline`",
2053
+ order: ORDER_OF_PIPELINE_JSON,
2054
+ value: __assign(__assign({}, pipeline), { tasks: tasks, knowledgeSources: knowledgeSources, knowledgePieces: [], personas: personas, preparations: [] }),
2055
+ });
1976
2056
  }
1977
2057
  /**
1978
2058
  * TODO: [🧿] Maybe do same process with same granularity and subfinctions as `preparePipeline`
@@ -4333,16 +4413,21 @@
4333
4413
  // Note: Wait a short time to prevent race conditions
4334
4414
  _g.sent();
4335
4415
  _g.label = 6;
4336
- case 6: return [2 /*return*/, $asDeeplyFrozenSerializableJson("Unuccessful PipelineExecutorResult (with missing parameter {".concat(parameter.name, "}) PipelineExecutorResult"), {
4337
- isSuccessful: false,
4338
- errors: __spreadArray([
4339
- new PipelineExecutionError("Parameter `{".concat(parameter.name, "}` is required as an input parameter"))
4340
- ], __read(errors), false).map(serializeError),
4341
- warnings: [],
4342
- executionReport: executionReport,
4343
- outputParameters: {},
4344
- usage: ZERO_USAGE,
4345
- preparedPipeline: preparedPipeline,
4416
+ case 6: return [2 /*return*/, exportJson({
4417
+ name: "executionReport",
4418
+ message: "Unuccessful PipelineExecutorResult (with missing parameter {".concat(parameter.name, "}) PipelineExecutorResult"),
4419
+ order: [],
4420
+ value: {
4421
+ isSuccessful: false,
4422
+ errors: __spreadArray([
4423
+ new PipelineExecutionError("Parameter `{".concat(parameter.name, "}` is required as an input parameter"))
4424
+ ], __read(errors), false).map(serializeError),
4425
+ warnings: [],
4426
+ executionReport: executionReport,
4427
+ outputParameters: {},
4428
+ usage: ZERO_USAGE,
4429
+ preparedPipeline: preparedPipeline,
4430
+ },
4346
4431
  })];
4347
4432
  case 7:
4348
4433
  _b = _a.next();
@@ -4381,16 +4466,21 @@
4381
4466
  // Note: Wait a short time to prevent race conditions
4382
4467
  _h.sent();
4383
4468
  _h.label = 3;
4384
- case 3: return [2 /*return*/, { value: $asDeeplyFrozenSerializableJson(spaceTrim.spaceTrim(function (block) { return "\n Unuccessful PipelineExecutorResult (with extra parameter {".concat(parameter.name, "}) PipelineExecutorResult\n\n ").concat(block(pipelineIdentification), "\n "); }), {
4385
- isSuccessful: false,
4386
- errors: __spreadArray([
4387
- new PipelineExecutionError(spaceTrim.spaceTrim(function (block) { return "\n Parameter `{".concat(parameter.name, "}` is passed as input parameter but it is not input\n\n ").concat(block(pipelineIdentification), "\n "); }))
4388
- ], __read(errors), false).map(serializeError),
4389
- warnings: warnings.map(serializeError),
4390
- executionReport: executionReport,
4391
- outputParameters: {},
4392
- usage: ZERO_USAGE,
4393
- preparedPipeline: preparedPipeline,
4469
+ case 3: return [2 /*return*/, { value: exportJson({
4470
+ name: 'pipelineExecutorResult',
4471
+ message: spaceTrim.spaceTrim(function (block) { return "\n Unuccessful PipelineExecutorResult (with extra parameter {".concat(parameter.name, "}) PipelineExecutorResult\n\n ").concat(block(pipelineIdentification), "\n "); }),
4472
+ order: [],
4473
+ value: {
4474
+ isSuccessful: false,
4475
+ errors: __spreadArray([
4476
+ new PipelineExecutionError(spaceTrim.spaceTrim(function (block) { return "\n Parameter `{".concat(parameter.name, "}` is passed as input parameter but it is not input\n\n ").concat(block(pipelineIdentification), "\n "); }))
4477
+ ], __read(errors), false).map(serializeError),
4478
+ warnings: warnings.map(serializeError),
4479
+ executionReport: executionReport,
4480
+ outputParameters: {},
4481
+ usage: ZERO_USAGE,
4482
+ preparedPipeline: preparedPipeline,
4483
+ },
4394
4484
  }) }];
4395
4485
  case 4: return [2 /*return*/];
4396
4486
  }
@@ -4544,14 +4634,19 @@
4544
4634
  // Note: Wait a short time to prevent race conditions
4545
4635
  _g.sent();
4546
4636
  _g.label = 27;
4547
- case 27: return [2 /*return*/, $asDeeplyFrozenSerializableJson('Unuccessful PipelineExecutorResult (with misc errors) PipelineExecutorResult', {
4548
- isSuccessful: false,
4549
- errors: __spreadArray([error_1], __read(errors), false).map(serializeError),
4550
- warnings: warnings.map(serializeError),
4551
- usage: usage_1,
4552
- executionReport: executionReport,
4553
- outputParameters: outputParameters_1,
4554
- preparedPipeline: preparedPipeline,
4637
+ case 27: return [2 /*return*/, exportJson({
4638
+ name: 'pipelineExecutorResult',
4639
+ message: "Unuccessful PipelineExecutorResult (with misc errors) PipelineExecutorResult",
4640
+ order: [],
4641
+ value: {
4642
+ isSuccessful: false,
4643
+ errors: __spreadArray([error_1], __read(errors), false).map(serializeError),
4644
+ warnings: warnings.map(serializeError),
4645
+ usage: usage_1,
4646
+ executionReport: executionReport,
4647
+ outputParameters: outputParameters_1,
4648
+ preparedPipeline: preparedPipeline,
4649
+ },
4555
4650
  })];
4556
4651
  case 28:
4557
4652
  usage = addUsage.apply(void 0, __spreadArray([], __read(executionReport.promptExecutions.map(function (_a) {
@@ -4572,14 +4667,19 @@
4572
4667
  // Note: Wait a short time to prevent race conditions
4573
4668
  _g.sent();
4574
4669
  _g.label = 30;
4575
- case 30: return [2 /*return*/, $asDeeplyFrozenSerializableJson('Successful PipelineExecutorResult', {
4576
- isSuccessful: true,
4577
- errors: errors.map(serializeError),
4578
- warnings: warnings.map(serializeError),
4579
- usage: usage,
4580
- executionReport: executionReport,
4581
- outputParameters: outputParameters,
4582
- preparedPipeline: preparedPipeline,
4670
+ case 30: return [2 /*return*/, exportJson({
4671
+ name: 'pipelineExecutorResult',
4672
+ message: "Successful PipelineExecutorResult",
4673
+ order: [],
4674
+ value: {
4675
+ isSuccessful: true,
4676
+ errors: errors.map(serializeError),
4677
+ warnings: warnings.map(serializeError),
4678
+ usage: usage,
4679
+ executionReport: executionReport,
4680
+ outputParameters: outputParameters,
4681
+ preparedPipeline: preparedPipeline,
4682
+ },
4583
4683
  })];
4584
4684
  }
4585
4685
  });
@@ -5444,36 +5544,6 @@
5444
5544
  * [ ] One piece can have multiple sources
5445
5545
  */
5446
5546
 
5447
- /**
5448
- * @@@
5449
- *
5450
- * Note: It is usefull @@@
5451
- *
5452
- * @param pipeline
5453
- * @public exported from `@promptbook/utils`
5454
- */
5455
- function clonePipeline(pipeline) {
5456
- // Note: Not using spread operator (...) because @@@
5457
- var pipelineUrl = pipeline.pipelineUrl, sourceFile = pipeline.sourceFile, title = pipeline.title, bookVersion = pipeline.bookVersion, description = pipeline.description, formfactorName = pipeline.formfactorName, parameters = pipeline.parameters, tasks = pipeline.tasks, knowledgeSources = pipeline.knowledgeSources, knowledgePieces = pipeline.knowledgePieces, personas = pipeline.personas, preparations = pipeline.preparations;
5458
- return {
5459
- pipelineUrl: pipelineUrl,
5460
- sourceFile: sourceFile,
5461
- title: title,
5462
- bookVersion: bookVersion,
5463
- description: description,
5464
- formfactorName: formfactorName,
5465
- parameters: parameters,
5466
- tasks: tasks,
5467
- knowledgeSources: knowledgeSources,
5468
- knowledgePieces: knowledgePieces,
5469
- personas: personas,
5470
- preparations: preparations,
5471
- };
5472
- }
5473
- /**
5474
- * TODO: [🍙] Make some standard order of json properties
5475
- */
5476
-
5477
5547
  /**
5478
5548
  * @@@
5479
5549
  *
@@ -5514,6 +5584,7 @@
5514
5584
  });
5515
5585
  }
5516
5586
  /**
5587
+ * TODO: [😂] Adding knowledge should be convert to async high-level abstractions, simmilar thing with expectations to sync high-level abstractions
5517
5588
  * TODO: [🧠] Add context to each task (if missing)
5518
5589
  * TODO: [🧠] What is better name `prepareTask` or `prepareTaskAndParameters`
5519
5590
  * TODO: [♨][main] !!! Prepare index the examples and maybe tasks
@@ -5602,11 +5673,19 @@
5602
5673
  case 3:
5603
5674
  tasksPrepared = (_c.sent()).tasksPrepared;
5604
5675
  // ----- /Tasks preparation -----
5676
+ // TODO: [😂] Use here all `AsyncHighLevelAbstraction`
5605
5677
  // Note: Count total usage
5606
5678
  currentPreparation.usage = llmToolsWithUsage.getTotalUsage();
5607
- return [2 /*return*/, $asDeeplyFrozenSerializableJson('Prepared PipelineJson', __assign(__assign({}, clonePipeline(pipeline)), { tasks: __spreadArray([], __read(tasksPrepared), false),
5608
- // <- TODO: [🪓] Here should be no need for spreading new array, just ` tasks: tasksPrepared`
5609
- knowledgeSources: knowledgeSourcesPrepared, knowledgePieces: knowledgePiecesPrepared, personas: preparedPersonas, preparations: __spreadArray([], __read(preparations), false) }))];
5679
+ return [2 /*return*/, exportJson({
5680
+ name: 'pipelineJson',
5681
+ message: "Result of `preparePipeline`",
5682
+ order: ORDER_OF_PIPELINE_JSON,
5683
+ value: __assign(__assign({}, pipeline), {
5684
+ // <- TODO: Probbably deeply clone the pipeline because `$exportJson` freezes the subobjects
5685
+ knowledgeSources: knowledgeSourcesPrepared, knowledgePieces: knowledgePiecesPrepared, tasks: __spreadArray([], __read(tasksPrepared), false),
5686
+ // <- TODO: [🪓] Here should be no need for spreading new array, just ` tasks: tasksPrepared`
5687
+ personas: preparedPersonas, preparations: __spreadArray([], __read(preparations), false) }),
5688
+ })];
5610
5689
  }
5611
5690
  });
5612
5691
  });
@@ -5870,7 +5949,8 @@
5870
5949
  expectResultingParameterName();
5871
5950
  var parameter = $pipelineJson.parameters.find(function (param) { return param.name === $taskJson.resultingParameterName; });
5872
5951
  if (parameter === undefined) {
5873
- throw new ParseError("Can not find parameter {".concat($taskJson.resultingParameterName, "} to assign example value on it"));
5952
+ // TODO: !!!!!! Change to logic error for higher level abstractions to work
5953
+ throw new ParseError("Parameter `{".concat($taskJson.resultingParameterName, "}` is not defined so can not define example value of it"));
5874
5954
  }
5875
5955
  parameter.exampleValues = parameter.exampleValues || [];
5876
5956
  parameter.exampleValues.push($taskJson.content);
@@ -6779,7 +6859,13 @@
6779
6859
  documentationUrl: "https://github.com/webgptorg/promptbook/discussions/184",
6780
6860
  pipelineInterface: {
6781
6861
  inputParameters: [
6782
- /* @@@ */
6862
+ /* @@@ */
6863
+ {
6864
+ name: 'nonce',
6865
+ description: 'Just to prevent GENERATOR to be set as implicit formfactor',
6866
+ isInput: true,
6867
+ isOutput: false,
6868
+ },
6783
6869
  ],
6784
6870
  outputParameters: [
6785
6871
  /* @@@ */
@@ -6825,7 +6911,13 @@
6825
6911
  documentationUrl: "https://github.com/webgptorg/promptbook/discussions/177",
6826
6912
  pipelineInterface: {
6827
6913
  inputParameters: [
6828
- /* @@@ */
6914
+ /* @@@ */
6915
+ {
6916
+ name: 'nonce',
6917
+ description: 'Just to prevent EXPERIMENTAL_MATCHER to be set as implicit formfactor',
6918
+ isInput: true,
6919
+ isOutput: false,
6920
+ },
6829
6921
  ],
6830
6922
  outputParameters: [
6831
6923
  /* @@@ */
@@ -6974,6 +7066,9 @@
6974
7066
  * Note: `$` is used to indicate that this function mutates given `pipelineJson`
6975
7067
  */
6976
7068
  $applyToPipelineJson: function (command, $pipelineJson) {
7069
+ if ($pipelineJson.formfactorName !== undefined && $pipelineJson.formfactorName !== command.formfactorName) {
7070
+ 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 ")));
7071
+ }
6977
7072
  $pipelineJson.formfactorName = command.formfactorName;
6978
7073
  },
6979
7074
  /**
@@ -7161,7 +7256,7 @@
7161
7256
  // <- TODO: [🚎][💩] Some better way how to get warnings from pipeline parsing / logic
7162
7257
  }
7163
7258
  else {
7164
- throw new ParseError(spaceTrim__default["default"]("\n Redefinition of MODEL `".concat(command.key, "` in the pipeline head\n\n You have used:\n - MODEL ").concat(command.key, " ").concat($pipelineJson.defaultModelRequirements[command.key], "\n - MODEL ").concat(command.key, " ").concat(command.value, "\n ")));
7259
+ 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 ")));
7165
7260
  }
7166
7261
  }
7167
7262
  $pipelineJson.defaultModelRequirements[command.key] = command.value;
@@ -7979,6 +8074,295 @@
7979
8074
  return null;
7980
8075
  }
7981
8076
 
8077
+ /**
8078
+ * @@@
8079
+ *
8080
+ * @deprecated https://github.com/webgptorg/promptbook/pull/186
8081
+ * @see https://github.com/webgptorg/promptbook/discussions/171
8082
+ *
8083
+ * @public exported from `@promptbook/core`
8084
+ */
8085
+ function getPipelineInterface(pipeline) {
8086
+ var e_1, _a, e_2, _b;
8087
+ var pipelineInterface = {
8088
+ inputParameters: [],
8089
+ outputParameters: [],
8090
+ };
8091
+ try {
8092
+ for (var _c = __values(pipeline.parameters), _d = _c.next(); !_d.done; _d = _c.next()) {
8093
+ var parameter = _d.value;
8094
+ var isInput = parameter.isInput, isOutput = parameter.isOutput;
8095
+ if (isInput) {
8096
+ pipelineInterface.inputParameters.push(deepClone(parameter));
8097
+ }
8098
+ if (isOutput) {
8099
+ pipelineInterface.outputParameters.push(deepClone(parameter));
8100
+ }
8101
+ }
8102
+ }
8103
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
8104
+ finally {
8105
+ try {
8106
+ if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
8107
+ }
8108
+ finally { if (e_1) throw e_1.error; }
8109
+ }
8110
+ try {
8111
+ for (var _e = __values(['inputParameters', 'outputParameters']), _f = _e.next(); !_f.done; _f = _e.next()) {
8112
+ var key = _f.value;
8113
+ pipelineInterface[key].sort(function (_a, _b) {
8114
+ var name1 = _a.name;
8115
+ var name2 = _b.name;
8116
+ return name1.localeCompare(name2);
8117
+ });
8118
+ }
8119
+ }
8120
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
8121
+ finally {
8122
+ try {
8123
+ if (_f && !_f.done && (_b = _e.return)) _b.call(_e);
8124
+ }
8125
+ finally { if (e_2) throw e_2.error; }
8126
+ }
8127
+ return exportJson({
8128
+ name: "pipelineInterface",
8129
+ message: "Result of `getPipelineInterface`",
8130
+ order: ['inputParameters', 'outputParameters'],
8131
+ value: pipelineInterface,
8132
+ });
8133
+ }
8134
+
8135
+ /**
8136
+ * @@@
8137
+ *
8138
+ * @deprecated https://github.com/webgptorg/promptbook/pull/186
8139
+ * @see https://github.com/webgptorg/promptbook/discussions/171
8140
+ *
8141
+ * @public exported from `@promptbook/core`
8142
+ */
8143
+ function isPipelineInterfacesEqual(pipelineInterface1, pipelineInterface2) {
8144
+ var e_1, _a, e_2, _b;
8145
+ try {
8146
+ for (var _c = __values(['inputParameters', 'outputParameters']), _d = _c.next(); !_d.done; _d = _c.next()) {
8147
+ var whichParameters = _d.value;
8148
+ var parameters1 = pipelineInterface1[whichParameters]; // <- Note: `isPipelineInterfacesEqual` is just temporary solution, no need to fix this
8149
+ var parameters2 = pipelineInterface2[whichParameters];
8150
+ if (parameters1.length !== parameters2.length) {
8151
+ return false;
8152
+ }
8153
+ var _loop_1 = function (parameter) {
8154
+ var matchingParameter = parameters2.find(function (_a) {
8155
+ var name = _a.name;
8156
+ return name === parameter.name;
8157
+ });
8158
+ if (!matchingParameter) {
8159
+ return { value: false };
8160
+ }
8161
+ // Note: Do not compare description, it is not relevant for compatibility
8162
+ if (matchingParameter.isInput !== parameter.isInput) {
8163
+ return { value: false };
8164
+ }
8165
+ if (matchingParameter.isOutput !== parameter.isOutput) {
8166
+ return { value: false };
8167
+ }
8168
+ };
8169
+ try {
8170
+ for (var parameters1_1 = (e_2 = void 0, __values(parameters1)), parameters1_1_1 = parameters1_1.next(); !parameters1_1_1.done; parameters1_1_1 = parameters1_1.next()) {
8171
+ var parameter = parameters1_1_1.value;
8172
+ var state_1 = _loop_1(parameter);
8173
+ if (typeof state_1 === "object")
8174
+ return state_1.value;
8175
+ }
8176
+ }
8177
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
8178
+ finally {
8179
+ try {
8180
+ if (parameters1_1_1 && !parameters1_1_1.done && (_b = parameters1_1.return)) _b.call(parameters1_1);
8181
+ }
8182
+ finally { if (e_2) throw e_2.error; }
8183
+ }
8184
+ }
8185
+ }
8186
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
8187
+ finally {
8188
+ try {
8189
+ if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
8190
+ }
8191
+ finally { if (e_1) throw e_1.error; }
8192
+ }
8193
+ return true;
8194
+ }
8195
+
8196
+ /**
8197
+ * @@@
8198
+ *
8199
+ * @deprecated https://github.com/webgptorg/promptbook/pull/186
8200
+ * @see https://github.com/webgptorg/promptbook/discussions/171
8201
+ *
8202
+ * @public exported from `@promptbook/core`
8203
+ */
8204
+ function isPipelineImplementingInterface(options) {
8205
+ var pipeline = options.pipeline, pipelineInterface = options.pipelineInterface;
8206
+ return isPipelineInterfacesEqual(getPipelineInterface(pipeline), pipelineInterface);
8207
+ }
8208
+
8209
+ /**
8210
+ * Set formfactor based on the pipeline interface e
8211
+ *
8212
+ * @private
8213
+ */
8214
+ var ImplicitFormfactorHla = {
8215
+ type: 'SYNC',
8216
+ $applyToPipelineJson: function ($pipelineJson) {
8217
+ var e_1, _a;
8218
+ if ($pipelineJson.formfactorName !== undefined) {
8219
+ // Note: When formfactor is already set, do nothing
8220
+ return;
8221
+ }
8222
+ try {
8223
+ for (var _b = __values(FORMFACTOR_DEFINITIONS.filter(function (_a) {
8224
+ var name = _a.name;
8225
+ return name !== 'GENERIC';
8226
+ })), _c = _b.next(); !_c.done; _c = _b.next()) {
8227
+ var formfactorDefinition = _c.value;
8228
+ // <- Note: [♓️][💩] This is the order of the formfactors, make some explicit priority
8229
+ var name_1 = formfactorDefinition.name, pipelineInterface = formfactorDefinition.pipelineInterface;
8230
+ var isCompatible = isPipelineImplementingInterface({
8231
+ pipeline: __assign({ formfactorName: name_1 }, $pipelineJson),
8232
+ pipelineInterface: pipelineInterface,
8233
+ });
8234
+ /*/
8235
+ console.log({
8236
+ subject: `${$pipelineJson.title} implements ${name}`,
8237
+ pipelineTitle: $pipelineJson.title,
8238
+ formfactorName: name,
8239
+ isCompatible,
8240
+ formfactorInterface: pipelineInterface,
8241
+ pipelineInterface: getPipelineInterface($pipelineJson as PipelineJson),
8242
+ });
8243
+ /**/
8244
+ if (isCompatible) {
8245
+ $pipelineJson.formfactorName = name_1;
8246
+ return;
8247
+ }
8248
+ }
8249
+ }
8250
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
8251
+ finally {
8252
+ try {
8253
+ if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
8254
+ }
8255
+ finally { if (e_1) throw e_1.error; }
8256
+ }
8257
+ },
8258
+ };
8259
+
8260
+ /**
8261
+ * Allow to define chatbot with no need to write full interface
8262
+ *
8263
+ * @private
8264
+ */
8265
+ var QuickChatbotHla = {
8266
+ type: 'SYNC',
8267
+ $applyToPipelineJson: function ($pipelineJson) {
8268
+ if ($pipelineJson.tasks.length !== 0) {
8269
+ // Note: When there are already tasks, do nothing
8270
+ return;
8271
+ }
8272
+ if ($pipelineJson.parameters.length !== 0) {
8273
+ // Note: When there are already parameters, do nothing
8274
+ return;
8275
+ }
8276
+ if ($pipelineJson.personas.length === 0) {
8277
+ // Note: When no personas defined, do nothing
8278
+ return;
8279
+ }
8280
+ var personaName = $pipelineJson.personas[0].name;
8281
+ $pipelineJson.formfactorName = 'CHATBOT';
8282
+ $pipelineJson.parameters.push({
8283
+ name: 'previousTitle',
8284
+ description: 'Previous title of the conversation',
8285
+ isInput: true,
8286
+ isOutput: false,
8287
+ }, {
8288
+ name: 'previousConversationSummary',
8289
+ description: 'Previous conversation summary',
8290
+ isInput: true,
8291
+ isOutput: false,
8292
+ }, {
8293
+ name: 'userMessage',
8294
+ description: 'User message',
8295
+ isInput: true,
8296
+ isOutput: false,
8297
+ }, {
8298
+ name: 'title',
8299
+ description: 'Title of the conversation',
8300
+ isInput: false,
8301
+ isOutput: true,
8302
+ }, {
8303
+ name: 'conversationSummary',
8304
+ description: 'Summary of the conversation',
8305
+ isInput: false,
8306
+ isOutput: true,
8307
+ }, {
8308
+ name: 'chatbotResponse',
8309
+ description: 'Chatbot response',
8310
+ isInput: false,
8311
+ isOutput: true,
8312
+ exampleValues: ['Hello, I am a Pavol`s virtual avatar. How can I help you?'],
8313
+ });
8314
+ // TODO: !!!!!! spaceTrim
8315
+ $pipelineJson.tasks.push({
8316
+ taskType: 'PROMPT_TASK',
8317
+ name: 'create-an-answer',
8318
+ title: 'Create an answer',
8319
+ content: 'Write a response to the user message:\n\n**Question from user**\n\n> {userMessage}\n\n**Previous conversation**\n\n> {previousConversationSummary}',
8320
+ resultingParameterName: 'chatbotResponse',
8321
+ personaName: personaName,
8322
+ dependentParameterNames: ['userMessage', 'previousConversationSummary' /* !!!!!!, 'knowledge'*/],
8323
+ // !!!!!! preparedContent: '{content}\n\n## Knowledge\n\n{knowledge}',
8324
+ }, {
8325
+ taskType: 'PROMPT_TASK',
8326
+ name: 'summarize-the-conversation',
8327
+ title: 'Summarize the conversation',
8328
+ content: 'Summarize the conversation in a few words:\n\n## Rules\n\n- Summarise the text of the conversation in a few words\n- Convert the text to its basic idea\n- Imagine you are writing the headline or subject line of an email\n- Respond with a few words of summary only\n\n## Conversation\n\n**User:**\n\n> {userMessage}\n\n**You:**\n\n> {chatbotResponse}',
8329
+ resultingParameterName: 'conversationSummary',
8330
+ personaName: personaName,
8331
+ expectations: {
8332
+ words: {
8333
+ min: 1,
8334
+ max: 10,
8335
+ },
8336
+ },
8337
+ dependentParameterNames: ['userMessage', 'chatbotResponse' /* !!!!!!, 'knowledge'*/],
8338
+ // !!!!!! preparedContent: '{content}\n\n## Knowledge\n\n{knowledge}',
8339
+ }, {
8340
+ taskType: 'SIMPLE_TASK',
8341
+ name: 'title',
8342
+ title: 'Title',
8343
+ content: '{conversationSummary}',
8344
+ resultingParameterName: 'title',
8345
+ dependentParameterNames: ['conversationSummary' /* !!!!!!, 'knowledge'*/],
8346
+ // !!!!!! preparedContent: '{content}\n\n## Knowledge\n\n{knowledge}',
8347
+ });
8348
+ },
8349
+ };
8350
+
8351
+ /**
8352
+ * All high-level abstractions
8353
+ *
8354
+ * @private internal index of `pipelineStringToJsonSync` (= used for sync) and `preparePipeline` (= used for async)
8355
+ */
8356
+ var HIGH_LEVEL_ABSTRACTIONS = [
8357
+ ImplicitFormfactorHla,
8358
+ QuickChatbotHla,
8359
+ // <- Note: [♓️][💩] This is the order of the application of high-level abstractions application on pipeline JSON
8360
+ ];
8361
+ /**
8362
+ * TODO: Test that all sync high-level abstractions are before async high-level abstractions
8363
+ * Note: [💞] Ignore a discrepancy between file name and entity name
8364
+ */
8365
+
7982
8366
  /**
7983
8367
  * Supported script languages
7984
8368
  *
@@ -8254,20 +8638,15 @@
8254
8638
  * @public exported from `@promptbook/core`
8255
8639
  */
8256
8640
  function pipelineStringToJsonSync(pipelineString) {
8257
- var e_1, _a, e_2, _b, e_3, _c, e_4, _d, e_5, _e;
8641
+ var e_1, _a, e_2, _b, e_3, _c, e_4, _d, e_5, _e, e_6, _f;
8258
8642
  var $pipelineJson = {
8259
- title: undefined /* <- Note: [🍙] Putting here placeholder to keep `title` on top at final JSON */,
8260
- pipelineUrl: undefined /* <- Note: Putting here placeholder to keep `pipelineUrl` on top at final JSON */,
8261
- bookVersion: undefined /* <- Note: By default no explicit version */,
8262
- description: undefined /* <- Note: [🍙] Putting here placeholder to keep `description` on top at final JSON */,
8263
- formfactorName: 'GENERIC',
8643
+ title: DEFAULT_TITLE,
8264
8644
  parameters: [],
8265
8645
  tasks: [],
8266
8646
  knowledgeSources: [],
8267
8647
  knowledgePieces: [],
8268
8648
  personas: [],
8269
8649
  preparations: [],
8270
- // <- TODO: [🍙] Some standard order of properties
8271
8650
  };
8272
8651
  function getPipelineIdentification() {
8273
8652
  // Note: This is a 😐 implementation of [🚞]
@@ -8283,7 +8662,7 @@
8283
8662
  // =============================================================
8284
8663
  // Note: 1️⃣ Parsing of the markdown into object
8285
8664
  if (pipelineString.startsWith('#!')) {
8286
- var _f = __read(pipelineString.split('\n')), shebangLine_1 = _f[0], restLines = _f.slice(1);
8665
+ var _g = __read(pipelineString.split('\n')), shebangLine_1 = _g[0], restLines = _g.slice(1);
8287
8666
  if (!(shebangLine_1 || '').includes('ptbk')) {
8288
8667
  throw new ParseError(spaceTrim.spaceTrim(function (block) { return "\n It seems that you try to parse a book file which has non-standard shebang line for book files:\n Shebang line must contain 'ptbk'\n\n You have:\n ".concat(block(shebangLine_1 || '(empty line)'), "\n\n It should look like this:\n #!/usr/bin/env ptbk\n\n ").concat(block(getPipelineIdentification()), "\n "); }));
8289
8668
  }
@@ -8293,7 +8672,7 @@
8293
8672
  pipelineString = flattenMarkdown(pipelineString) /* <- Note: [🥞] */;
8294
8673
  pipelineString = pipelineString.replaceAll(/`\{(?<parameterName>[a-z0-9_]+)\}`/gi, '{$<parameterName>}');
8295
8674
  pipelineString = pipelineString.replaceAll(/`->\s+\{(?<parameterName>[a-z0-9_]+)\}`/gi, '-> {$<parameterName>}');
8296
- var _g = __read(splitMarkdownIntoSections(pipelineString).map(parseMarkdownSection)), pipelineHead = _g[0], pipelineSections = _g.slice(1); /* <- Note: [🥞] */
8675
+ var _h = __read(splitMarkdownIntoSections(pipelineString).map(parseMarkdownSection)), pipelineHead = _h[0], pipelineSections = _h.slice(1); /* <- Note: [🥞] */
8297
8676
  if (pipelineHead === undefined) {
8298
8677
  throw new UnexpectedError(spaceTrim.spaceTrim(function (block) { return "\n Pipeline head is not defined\n\n ".concat(block(getPipelineIdentification()), "\n\n This should never happen, because the pipeline already flattened\n "); }));
8299
8678
  }
@@ -8358,7 +8737,7 @@
8358
8737
  }
8359
8738
  try {
8360
8739
  commandParser.$applyToPipelineJson(command, $pipelineJson);
8361
- // <- Note: [🦦] Its strange that this assertion must be here, [🦦][4] should do this assertion implicitelly
8740
+ // <- Note: [🦦] Its strange that this assertion must be here, [🦦][4] should do this assertion implicitly
8362
8741
  }
8363
8742
  catch (error) {
8364
8743
  if (!(error instanceof ParseError)) {
@@ -8415,10 +8794,10 @@
8415
8794
  return nameWithSuffix;
8416
8795
  };
8417
8796
  var _loop_2 = function (section) {
8418
- var e_6, _m, e_7, _o;
8797
+ var e_7, _q, e_8, _r;
8419
8798
  // TODO: Parse section's description (the content out of the codeblock and lists)
8420
8799
  var listItems_2 = extractAllListItemsFromMarkdown(section.content);
8421
- var _p = extractOneBlockFromMarkdown(section.content), language = _p.language, content = _p.content;
8800
+ var _s = extractOneBlockFromMarkdown(section.content), language = _s.language, content = _s.content;
8422
8801
  // TODO: [🎾][1] DRY description
8423
8802
  var description_1 = section.content;
8424
8803
  // Note: Remove codeblocks - TODO: [🎾]
@@ -8466,7 +8845,7 @@
8466
8845
  }
8467
8846
  try {
8468
8847
  commandParser.$applyToTaskJson(
8469
- // <- Note: [🦦] Its strange that this assertion must be here, [🦦][4] should do this assertion implicitelly
8848
+ // <- Note: [🦦] Its strange that this assertion must be here, [🦦][4] should do this assertion implicitly
8470
8849
  command, $taskJson, $pipelineJson);
8471
8850
  }
8472
8851
  catch (error) {
@@ -8482,17 +8861,17 @@
8482
8861
  };
8483
8862
  try {
8484
8863
  // TODO [♓️] List commands and before apply order them to achieve order-agnostic commands
8485
- for (var commands_1 = (e_6 = void 0, __values(commands)), commands_1_1 = commands_1.next(); !commands_1_1.done; commands_1_1 = commands_1.next()) {
8486
- var _q = commands_1_1.value, listItem = _q.listItem, command = _q.command;
8864
+ for (var commands_1 = (e_7 = void 0, __values(commands)), commands_1_1 = commands_1.next(); !commands_1_1.done; commands_1_1 = commands_1.next()) {
8865
+ var _t = commands_1_1.value, listItem = _t.listItem, command = _t.command;
8487
8866
  _loop_4(listItem, command);
8488
8867
  }
8489
8868
  }
8490
- catch (e_6_1) { e_6 = { error: e_6_1 }; }
8869
+ catch (e_7_1) { e_7 = { error: e_7_1 }; }
8491
8870
  finally {
8492
8871
  try {
8493
- if (commands_1_1 && !commands_1_1.done && (_m = commands_1.return)) _m.call(commands_1);
8872
+ if (commands_1_1 && !commands_1_1.done && (_q = commands_1.return)) _q.call(commands_1);
8494
8873
  }
8495
- finally { if (e_6) throw e_6.error; }
8874
+ finally { if (e_7) throw e_7.error; }
8496
8875
  }
8497
8876
  // TODO: [🍧] Should be done in SECTION command
8498
8877
  if ($taskJson.taskType === 'SCRIPT_TASK') {
@@ -8506,8 +8885,8 @@
8506
8885
  }
8507
8886
  $taskJson.dependentParameterNames = Array.from(extractParameterNamesFromTask($taskJson));
8508
8887
  try {
8509
- for (var _r = (e_7 = void 0, __values($taskJson.dependentParameterNames)), _s = _r.next(); !_s.done; _s = _r.next()) {
8510
- var parameterName = _s.value;
8888
+ for (var _u = (e_8 = void 0, __values($taskJson.dependentParameterNames)), _v = _u.next(); !_v.done; _v = _u.next()) {
8889
+ var parameterName = _v.value;
8511
8890
  // TODO: [🧠] This definition should be made first in the task
8512
8891
  defineParam({
8513
8892
  parameterName: parameterName,
@@ -8518,12 +8897,12 @@
8518
8897
  });
8519
8898
  }
8520
8899
  }
8521
- catch (e_7_1) { e_7 = { error: e_7_1 }; }
8900
+ catch (e_8_1) { e_8 = { error: e_8_1 }; }
8522
8901
  finally {
8523
8902
  try {
8524
- if (_s && !_s.done && (_o = _r.return)) _o.call(_r);
8903
+ if (_v && !_v.done && (_r = _u.return)) _r.call(_u);
8525
8904
  }
8526
- finally { if (e_7) throw e_7.error; }
8905
+ finally { if (e_8) throw e_8.error; }
8527
8906
  }
8528
8907
  /*
8529
8908
  // TODO: [🍧] This should be checked in `MODEL` command + better error message
@@ -8572,18 +8951,22 @@
8572
8951
  var isThisParameterResulting = $pipelineJson.tasks.some(function (task) { return task.resultingParameterName === parameter.name; });
8573
8952
  if (!isThisParameterResulting) {
8574
8953
  parameter.isInput = true;
8954
+ // <- TODO: [💔] Why this is making typescript error in vscode but not in cli
8955
+ // > Type 'true' is not assignable to type 'false'.ts(2322)
8956
+ // > (property) isInput: false
8957
+ // > The parameter is input of the pipeline The parameter is NOT input of the pipeline
8575
8958
  }
8576
8959
  };
8577
8960
  try {
8578
- for (var _h = __values($pipelineJson.parameters), _j = _h.next(); !_j.done; _j = _h.next()) {
8579
- var parameter = _j.value;
8961
+ for (var _j = __values($pipelineJson.parameters), _k = _j.next(); !_k.done; _k = _j.next()) {
8962
+ var parameter = _k.value;
8580
8963
  _loop_3(parameter);
8581
8964
  }
8582
8965
  }
8583
8966
  catch (e_4_1) { e_4 = { error: e_4_1 }; }
8584
8967
  finally {
8585
8968
  try {
8586
- if (_j && !_j.done && (_d = _h.return)) _d.call(_h);
8969
+ if (_k && !_k.done && (_d = _j.return)) _d.call(_j);
8587
8970
  }
8588
8971
  finally { if (e_4) throw e_4.error; }
8589
8972
  }
@@ -8592,17 +8975,18 @@
8592
8975
  // Note: 7️⃣ Mark all non-INPUT parameters as OUTPUT if any OUTPUT is not set
8593
8976
  if ($pipelineJson.parameters.every(function (parameter) { return !parameter.isOutput; })) {
8594
8977
  try {
8595
- for (var _k = __values($pipelineJson.parameters), _l = _k.next(); !_l.done; _l = _k.next()) {
8596
- var parameter = _l.value;
8978
+ for (var _l = __values($pipelineJson.parameters), _m = _l.next(); !_m.done; _m = _l.next()) {
8979
+ var parameter = _m.value;
8597
8980
  if (!parameter.isInput) {
8598
8981
  parameter.isOutput = true;
8982
+ // <- TODO: [💔]
8599
8983
  }
8600
8984
  }
8601
8985
  }
8602
8986
  catch (e_5_1) { e_5 = { error: e_5_1 }; }
8603
8987
  finally {
8604
8988
  try {
8605
- if (_l && !_l.done && (_e = _k.return)) _e.call(_k);
8989
+ if (_m && !_m.done && (_e = _l.return)) _e.call(_l);
8606
8990
  }
8607
8991
  finally { if (e_5) throw e_5.error; }
8608
8992
  }
@@ -8610,7 +8994,7 @@
8610
8994
  // =============================================================
8611
8995
  // Note: 8️⃣ Cleanup of undefined values
8612
8996
  $pipelineJson.tasks.forEach(function (tasks) {
8613
- var e_8, _a;
8997
+ var e_9, _a;
8614
8998
  try {
8615
8999
  for (var _b = __values(Object.entries(tasks)), _c = _b.next(); !_c.done; _c = _b.next()) {
8616
9000
  var _d = __read(_c.value, 2), key = _d[0], value = _d[1];
@@ -8619,16 +9003,16 @@
8619
9003
  }
8620
9004
  }
8621
9005
  }
8622
- catch (e_8_1) { e_8 = { error: e_8_1 }; }
9006
+ catch (e_9_1) { e_9 = { error: e_9_1 }; }
8623
9007
  finally {
8624
9008
  try {
8625
9009
  if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
8626
9010
  }
8627
- finally { if (e_8) throw e_8.error; }
9011
+ finally { if (e_9) throw e_9.error; }
8628
9012
  }
8629
9013
  });
8630
9014
  $pipelineJson.parameters.forEach(function (parameter) {
8631
- var e_9, _a;
9015
+ var e_10, _a;
8632
9016
  try {
8633
9017
  for (var _b = __values(Object.entries(parameter)), _c = _b.next(); !_c.done; _c = _b.next()) {
8634
9018
  var _d = __read(_c.value, 2), key = _d[0], value = _d[1];
@@ -8637,19 +9021,49 @@
8637
9021
  }
8638
9022
  }
8639
9023
  }
8640
- catch (e_9_1) { e_9 = { error: e_9_1 }; }
9024
+ catch (e_10_1) { e_10 = { error: e_10_1 }; }
8641
9025
  finally {
8642
9026
  try {
8643
9027
  if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
8644
9028
  }
8645
- finally { if (e_9) throw e_9.error; }
9029
+ finally { if (e_10) throw e_10.error; }
8646
9030
  }
8647
9031
  });
9032
+ try {
9033
+ // =============================================================
9034
+ // Note: 9️⃣ Apply sync high-level abstractions
9035
+ for (var _o = __values(HIGH_LEVEL_ABSTRACTIONS.filter(function (_a) {
9036
+ var type = _a.type;
9037
+ return type === 'SYNC';
9038
+ })), _p = _o.next(); !_p.done; _p = _o.next()) {
9039
+ var highLevelAbstraction = _p.value;
9040
+ highLevelAbstraction.$applyToPipelineJson($pipelineJson);
9041
+ }
9042
+ }
9043
+ catch (e_6_1) { e_6 = { error: e_6_1 }; }
9044
+ finally {
9045
+ try {
9046
+ if (_p && !_p.done && (_f = _o.return)) _f.call(_o);
9047
+ }
9048
+ finally { if (e_6) throw e_6.error; }
9049
+ }
9050
+ // =============================================================
9051
+ // Note: 🔟 Default formfactor
9052
+ // Note: [🔆] If formfactor is still not set, set it to 'GENERIC'
9053
+ if ($pipelineJson.formfactorName === undefined) {
9054
+ $pipelineJson.formfactorName = 'GENERIC';
9055
+ }
8648
9056
  // =============================================================
8649
9057
  // TODO: [🍙] Maybe do reorder of `$pipelineJson` here
8650
- return $asDeeplyFrozenSerializableJson('pipelineJson', $pipelineJson);
9058
+ return exportJson({
9059
+ name: 'pipelineJson',
9060
+ message: "Result of `pipelineStringToJsonSync`",
9061
+ order: ORDER_OF_PIPELINE_JSON,
9062
+ value: __assign({ formfactorName: 'GENERIC' }, $pipelineJson),
9063
+ });
8651
9064
  }
8652
9065
  /**
9066
+ * TODO: [🧠] Maybe more things here can be refactored as high-level abstractions
8653
9067
  * TODO: [main] !!!! Warn if used only sync version
8654
9068
  * TODO: [🚞] Report here line/column of error
8655
9069
  * TODO: Use spaceTrim more effectively
@@ -8693,7 +9107,7 @@
8693
9107
  pipelineJson = _a.sent();
8694
9108
  _a.label = 2;
8695
9109
  case 2:
8696
- // Note: No need to use `$asDeeplyFrozenSerializableJson` because `pipelineStringToJsonSync` and `preparePipeline` already do that
9110
+ // Note: No need to use `$exportJson` because `pipelineStringToJsonSync` and `preparePipeline` already do that
8697
9111
  return [2 /*return*/, pipelineJson];
8698
9112
  }
8699
9113
  });
@@ -10150,7 +10564,7 @@
10150
10564
  return [3 /*break*/, 7];
10151
10565
  case 6:
10152
10566
  if (isVerbose) {
10153
- console.info(colors__default["default"].gray("Skipped file ".concat(fileName.split('\\').join('/'), " \u2013\u2060\u2060\u2060\u2060\u2060\u2060\u2060\u2060\u2060\u2060\u2060\u2060\u2060\u2060\u2060\u2060 Not a pipeline")));
10567
+ console.info(colors__default["default"].gray("Skipped file ".concat(fileName.split('\\').join('/'), " \u2013\u2060\u2060\u2060\u2060\u2060\u2060\u2060\u2060\u2060\u2060\u2060\u2060\u2060\u2060\u2060\u2060 Not a book")));
10154
10568
  }
10155
10569
  _e.label = 7;
10156
10570
  case 7:
@@ -10197,7 +10611,7 @@
10197
10611
  if (!(error_1 instanceof Error)) {
10198
10612
  throw error_1;
10199
10613
  }
10200
- wrappedErrorMessage = spaceTrim__default["default"](function (block) { return "\n ".concat(error_1.name, " in pipeline ").concat(fileName.split('\\').join('/'), "\u2060:\n\n ").concat(block(error_1.message), "\n\n "); });
10614
+ wrappedErrorMessage = spaceTrim__default["default"](function (block) { return "\n ".concat(error_1.name, " in pipeline ").concat(fileName.split('\\').join('/'), "\u2060:\n\n Original error message:\n ").concat(block(error_1.message), "\n\n Original stack trace:\n ").concat(block(error_1.stack || ''), "\n\n ---\n\n "); }) + '\n';
10201
10615
  if (isCrashedOnError) {
10202
10616
  throw new CollectionError(wrappedErrorMessage);
10203
10617
  }
@@ -10253,6 +10667,7 @@
10253
10667
  * TODO: Maybe move from `@promptbook/node` to `@promptbook/core` as we removes direct dependency on `fs`
10254
10668
  */
10255
10669
 
10670
+ // <- TODO: !!!!!!! Auto convert to type `import { ... } from 'type-fest';`
10256
10671
  /**
10257
10672
  * Tests if the value is [🚉] serializable as JSON
10258
10673
  *
@@ -10274,7 +10689,7 @@
10274
10689
  */
10275
10690
  function isSerializableAsJson(value) {
10276
10691
  try {
10277
- checkSerializableAsJson('', value);
10692
+ checkSerializableAsJson({ value: value });
10278
10693
  return true;
10279
10694
  }
10280
10695
  catch (error) {