@promptbook/website-crawler 0.72.0-30 โ†’ 0.72.0-32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/esm/index.es.js CHANGED
@@ -2,12 +2,13 @@ import spaceTrim$1, { spaceTrim } from 'spacetrim';
2
2
  import { Readability } from '@mozilla/readability';
3
3
  import { JSDOM } from 'jsdom';
4
4
  import { Converter } from 'showdown';
5
+ import { SHA256 } from 'crypto-js';
6
+ import hexEncoder from 'crypto-js/enc-hex';
7
+ import { mkdir, rm } from 'fs/promises';
8
+ import { basename, join, dirname } from 'path';
5
9
  import { format } from 'prettier';
6
10
  import parserHtml from 'prettier/parser-html';
7
- import { basename, join } from 'path';
8
11
  import { forTime } from 'waitasecond';
9
- import { SHA256 } from 'crypto-js';
10
- import hexEncoder from 'crypto-js/enc-hex';
11
12
  import { lookup } from 'mime-types';
12
13
  import { unparse, parse } from 'papaparse';
13
14
 
@@ -15,7 +16,7 @@ import { unparse, parse } from 'papaparse';
15
16
  /**
16
17
  * The version of the Promptbook library
17
18
  */
18
- var PROMPTBOOK_VERSION = '0.72.0-29';
19
+ var PROMPTBOOK_VERSION = '0.72.0-31';
19
20
  // TODO: [main] !!!! List here all the versions and annotate + put into script
20
21
 
21
22
  /*! *****************************************************************************
@@ -363,6 +364,12 @@ var LOOP_LIMIT = 1000;
363
364
  * @private within the repository - too low-level in comparison with other `MAX_...`
364
365
  */
365
366
  var IMMEDIATE_TIME = 10;
367
+ /**
368
+ * Strategy for caching the intermediate results for knowledge sources
369
+ *
370
+ * @public exported from `@promptbook/core`
371
+ */
372
+ var DEFAULT_INTERMEDIATE_FILES_STRATEGY = 'HIDE_AND_KEEP';
366
373
  // <- TODO: [๐Ÿ˜ก] Change to 'VISIBLE'
367
374
  /**
368
375
  * The maximum number of (LLM) tasks running in parallel
@@ -376,6 +383,14 @@ var DEFAULT_MAX_PARALLEL_COUNT = 5; // <- TODO: [๐Ÿคนโ€โ™‚๏ธ]
376
383
  * @public exported from `@promptbook/core`
377
384
  */
378
385
  var DEFAULT_MAX_EXECUTION_ATTEMPTS = 3; // <- TODO: [๐Ÿคนโ€โ™‚๏ธ]
386
+ /**
387
+ * Where to store the scrape cache
388
+ *
389
+ * Note: When the folder does not exist, it is created recursively
390
+ *
391
+ * @public exported from `@promptbook/core`
392
+ */
393
+ var DEFAULT_SCRAPE_CACHE_DIRNAME = '/.promptbook/scrape-cache';
379
394
  /**
380
395
  * Nonce which is used for replacing things in strings
381
396
  *
@@ -633,1290 +648,1425 @@ var websiteScraperMetadata = $deepFreeze({
633
648
  $scrapersMetadataRegister.register(websiteScraperMetadata);
634
649
 
635
650
  /**
636
- * Just marks a place of place where should be something implemented
651
+ * This error type indicates that you try to use a feature that is not available in the current environment
652
+ *
653
+ * @public exported from `@promptbook/core`
654
+ */
655
+ var EnvironmentMismatchError = /** @class */ (function (_super) {
656
+ __extends(EnvironmentMismatchError, _super);
657
+ function EnvironmentMismatchError(message) {
658
+ var _this = _super.call(this, message) || this;
659
+ _this.name = 'EnvironmentMismatchError';
660
+ Object.setPrototypeOf(_this, EnvironmentMismatchError.prototype);
661
+ return _this;
662
+ }
663
+ return EnvironmentMismatchError;
664
+ }(Error));
665
+
666
+ /**
667
+ * This error indicates that the promptbook can not retrieve knowledge from external sources
668
+ *
669
+ * @public exported from `@promptbook/core`
670
+ */
671
+ var KnowledgeScrapeError = /** @class */ (function (_super) {
672
+ __extends(KnowledgeScrapeError, _super);
673
+ function KnowledgeScrapeError(message) {
674
+ var _this = _super.call(this, message) || this;
675
+ _this.name = 'KnowledgeScrapeError';
676
+ Object.setPrototypeOf(_this, KnowledgeScrapeError.prototype);
677
+ return _this;
678
+ }
679
+ return KnowledgeScrapeError;
680
+ }(Error));
681
+
682
+ /**
683
+ * Just says that the variable is not used but should be kept
637
684
  * No side effects.
638
685
  *
639
- * Note: It can be usefull suppressing eslint errors of unused variables
686
+ * Note: It can be usefull for:
687
+ *
688
+ * 1) Suppressing eager optimization of unused imports
689
+ * 2) Suppressing eslint errors of unused variables in the tests
690
+ * 3) Keeping the type of the variable for type testing
640
691
  *
641
692
  * @param value any values
642
693
  * @returns void
643
694
  * @private within the repository
644
695
  */
645
- function TODO_USE() {
646
- var value = [];
696
+ function keepUnused() {
697
+ var valuesToKeep = [];
647
698
  for (var _i = 0; _i < arguments.length; _i++) {
648
- value[_i] = arguments[_i];
699
+ valuesToKeep[_i] = arguments[_i];
649
700
  }
650
701
  }
651
702
 
652
- var PipelineCollection = [{title:"Prepare Knowledge from Markdown",pipelineUrl:"https://promptbook.studio/promptbook/prepare-knowledge-from-markdown.ptbk.md",parameters:[{name:"knowledgeContent",description:"Markdown document content",isInput:true,isOutput:false},{name:"knowledgePieces",description:"The knowledge JSON object",isInput:false,isOutput:true}],templates:[{templateType:"PROMPT_TEMPLATE",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:"./promptbook-collection/prepare-knowledge-from-markdown.ptbk.md"},{title:"Prepare Keywords",pipelineUrl:"https://promptbook.studio/promptbook/prepare-knowledge-keywords.ptbk.md",parameters:[{name:"knowledgePieceContent",description:"The content",isInput:true,isOutput:false},{name:"keywords",description:"Keywords separated by comma",isInput:false,isOutput:true}],templates:[{templateType:"PROMPT_TEMPLATE",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:"./promptbook-collection/prepare-knowledge-keywords.ptbk.md"},{title:"Prepare Title",pipelineUrl:"https://promptbook.studio/promptbook/prepare-knowledge-title.ptbk.md",parameters:[{name:"knowledgePieceContent",description:"The content",isInput:true,isOutput:false},{name:"title",description:"The title of the document",isInput:false,isOutput:true}],templates:[{templateType:"PROMPT_TEMPLATE",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:"./promptbook-collection/prepare-knowledge-title.ptbk.md"},{title:"Prepare Keywords",pipelineUrl:"https://promptbook.studio/promptbook/prepare-persona.ptbk.md",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}],templates:[{templateType:"PROMPT_TEMPLATE",name:"make-model-requirements",title:"Make modelRequirements",content:"You are experienced AI engineer, you need to create virtual assistant.\nWrite\n\n## Sample\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:"./promptbook-collection/prepare-persona.ptbk.md"}];
653
-
654
703
  /**
655
- * Prettify the html code
704
+ * Just marks a place of place where should be something implemented
705
+ * No side effects.
656
706
  *
657
- * @param content raw html code
658
- * @returns formatted html code
659
- * @private withing the package because of HUGE size of prettier dependency
707
+ * Note: It can be usefull suppressing eslint errors of unused variables
708
+ *
709
+ * @param value any values
710
+ * @returns void
711
+ * @private within the repository
660
712
  */
661
- function prettifyMarkdown(content) {
662
- try {
663
- return format(content, {
664
- parser: 'markdown',
665
- plugins: [parserHtml],
666
- // TODO: DRY - make some import or auto-copy of .prettierrc
667
- endOfLine: 'lf',
668
- tabWidth: 4,
669
- singleQuote: true,
670
- trailingComma: 'all',
671
- arrowParens: 'always',
672
- printWidth: 120,
673
- htmlWhitespaceSensitivity: 'ignore',
674
- jsxBracketSameLine: false,
675
- bracketSpacing: true,
676
- });
677
- }
678
- catch (error) {
679
- // TODO: [๐ŸŸฅ] Detect browser / node and make it colorfull
680
- console.error('There was an error with prettifying the markdown, using the original as the fallback', {
681
- error: error,
682
- html: content,
683
- });
684
- return content;
713
+ function TODO_USE() {
714
+ var value = [];
715
+ for (var _i = 0; _i < arguments.length; _i++) {
716
+ value[_i] = arguments[_i];
685
717
  }
686
718
  }
687
719
 
688
720
  /**
689
- * Makes first letter of a string uppercase
721
+ * Tests if given string is valid URL.
690
722
  *
691
- * @public exported from `@promptbook/utils`
692
- */
693
- function capitalize(word) {
694
- return word.substring(0, 1).toUpperCase() + word.substring(1);
695
- }
696
-
697
- /**
698
- * Converts promptbook in JSON format to string format
723
+ * Note: Dataurl are considered perfectly valid.
724
+ * Note: There are two simmilar functions:
725
+ * - `isValidUrl` which tests any URL
726
+ * - `isValidPipelineUrl` *(this one)* which tests just promptbook URL
699
727
  *
700
- * @param pipelineJson Promptbook in JSON format (.ptbk.json)
701
- * @returns Promptbook in string format (.ptbk.md)
702
- * @public exported from `@promptbook/core`
728
+ * @public exported from `@promptbook/utils`
703
729
  */
704
- function pipelineJsonToString(pipelineJson) {
705
- var e_1, _a, e_2, _b, e_3, _c, e_4, _d, e_5, _e, e_6, _f;
706
- var title = pipelineJson.title, pipelineUrl = pipelineJson.pipelineUrl, promptbookVersion = pipelineJson.promptbookVersion, description = pipelineJson.description, parameters = pipelineJson.parameters, templates = pipelineJson.templates;
707
- var pipelineString = "# ".concat(title);
708
- if (description) {
709
- pipelineString += '\n\n';
710
- pipelineString += description;
711
- }
712
- var commands = [];
713
- if (pipelineUrl) {
714
- commands.push("PIPELINE URL ".concat(pipelineUrl));
730
+ function isValidUrl(url) {
731
+ if (typeof url !== 'string') {
732
+ return false;
715
733
  }
716
- commands.push("PROMPTBOOK VERSION ".concat(promptbookVersion));
717
- // TODO: [main] !!! This increase size of the bundle and is probbably not necessary
718
- pipelineString = prettifyMarkdown(pipelineString);
719
734
  try {
720
- for (var _g = __values(parameters.filter(function (_a) {
721
- var isInput = _a.isInput;
722
- return isInput;
723
- })), _h = _g.next(); !_h.done; _h = _g.next()) {
724
- var parameter = _h.value;
725
- commands.push("INPUT PARAMETER ".concat(templateParameterJsonToString(parameter)));
726
- }
727
- }
728
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
729
- finally {
730
- try {
731
- if (_h && !_h.done && (_a = _g.return)) _a.call(_g);
735
+ if (url.startsWith('blob:')) {
736
+ url = url.replace(/^blob:/, '');
732
737
  }
733
- finally { if (e_1) throw e_1.error; }
734
- }
735
- try {
736
- for (var _j = __values(parameters.filter(function (_a) {
737
- var isOutput = _a.isOutput;
738
- return isOutput;
739
- })), _k = _j.next(); !_k.done; _k = _j.next()) {
740
- var parameter = _k.value;
741
- commands.push("OUTPUT PARAMETER ".concat(templateParameterJsonToString(parameter)));
738
+ var urlObject = new URL(url /* because fail is handled */);
739
+ if (!['http:', 'https:', 'data:'].includes(urlObject.protocol)) {
740
+ return false;
742
741
  }
742
+ return true;
743
743
  }
744
- catch (e_2_1) { e_2 = { error: e_2_1 }; }
745
- finally {
746
- try {
747
- if (_k && !_k.done && (_b = _j.return)) _b.call(_j);
748
- }
749
- finally { if (e_2) throw e_2.error; }
750
- }
751
- pipelineString += '\n\n';
752
- pipelineString += commands.map(function (command) { return "- ".concat(command); }).join('\n');
753
- try {
754
- for (var templates_1 = __values(templates), templates_1_1 = templates_1.next(); !templates_1_1.done; templates_1_1 = templates_1.next()) {
755
- var template = templates_1_1.value;
756
- var
757
- /* Note: Not using:> name, */
758
- title_1 = template.title, description_1 = template.description,
759
- /* Note: dependentParameterNames, */
760
- jokers = template.jokerParameterNames, templateType = template.templateType, content = template.content, postprocessing = template.postprocessingFunctionNames, expectations = template.expectations, format = template.format, resultingParameterName = template.resultingParameterName;
761
- pipelineString += '\n\n';
762
- pipelineString += "## ".concat(title_1);
763
- if (description_1) {
764
- pipelineString += '\n\n';
765
- pipelineString += description_1;
766
- }
767
- var commands_1 = [];
768
- var contentLanguage = 'text';
769
- if (templateType === 'PROMPT_TEMPLATE') {
770
- var modelRequirements = template.modelRequirements;
771
- var _l = modelRequirements || {}, modelName = _l.modelName, modelVariant = _l.modelVariant;
772
- commands_1.push("EXECUTE PROMPT TEMPLATE");
773
- if (modelVariant) {
774
- commands_1.push("MODEL VARIANT ".concat(capitalize(modelVariant)));
775
- }
776
- if (modelName) {
777
- commands_1.push("MODEL NAME `".concat(modelName, "`"));
778
- }
779
- }
780
- else if (templateType === 'SIMPLE_TEMPLATE') {
781
- commands_1.push("SIMPLE TEMPLATE");
782
- // Note: Nothing special here
783
- }
784
- else if (templateType === 'SCRIPT_TEMPLATE') {
785
- commands_1.push("SCRIPT TEMPLATE");
786
- if (template.contentLanguage) {
787
- contentLanguage = template.contentLanguage;
788
- }
789
- else {
790
- contentLanguage = '';
791
- }
792
- }
793
- else if (templateType === 'DIALOG_TEMPLATE') {
794
- commands_1.push("DIALOG TEMPLATE");
795
- // Note: Nothing special here
796
- } // <- }else if([๐Ÿ…ฑ]
797
- if (jokers) {
798
- try {
799
- for (var jokers_1 = (e_4 = void 0, __values(jokers)), jokers_1_1 = jokers_1.next(); !jokers_1_1.done; jokers_1_1 = jokers_1.next()) {
800
- var joker = jokers_1_1.value;
801
- commands_1.push("JOKER {".concat(joker, "}"));
802
- }
803
- }
804
- catch (e_4_1) { e_4 = { error: e_4_1 }; }
805
- finally {
806
- try {
807
- if (jokers_1_1 && !jokers_1_1.done && (_d = jokers_1.return)) _d.call(jokers_1);
808
- }
809
- finally { if (e_4) throw e_4.error; }
810
- }
811
- } /* not else */
812
- if (postprocessing) {
813
- try {
814
- for (var postprocessing_1 = (e_5 = void 0, __values(postprocessing)), postprocessing_1_1 = postprocessing_1.next(); !postprocessing_1_1.done; postprocessing_1_1 = postprocessing_1.next()) {
815
- var postprocessingFunctionName = postprocessing_1_1.value;
816
- commands_1.push("POSTPROCESSING `".concat(postprocessingFunctionName, "`"));
817
- }
818
- }
819
- catch (e_5_1) { e_5 = { error: e_5_1 }; }
820
- finally {
821
- try {
822
- if (postprocessing_1_1 && !postprocessing_1_1.done && (_e = postprocessing_1.return)) _e.call(postprocessing_1);
823
- }
824
- finally { if (e_5) throw e_5.error; }
825
- }
826
- } /* not else */
827
- if (expectations) {
828
- try {
829
- for (var _m = (e_6 = void 0, __values(Object.entries(expectations))), _o = _m.next(); !_o.done; _o = _m.next()) {
830
- var _p = __read(_o.value, 2), unit = _p[0], _q = _p[1], min = _q.min, max = _q.max;
831
- if (min === max) {
832
- commands_1.push("EXPECT EXACTLY ".concat(min, " ").concat(capitalize(unit + (min > 1 ? 's' : ''))));
833
- }
834
- else {
835
- if (min !== undefined) {
836
- commands_1.push("EXPECT MIN ".concat(min, " ").concat(capitalize(unit + (min > 1 ? 's' : ''))));
837
- } /* not else */
838
- if (max !== undefined) {
839
- commands_1.push("EXPECT MAX ".concat(max, " ").concat(capitalize(unit + (max > 1 ? 's' : ''))));
840
- }
841
- }
842
- }
843
- }
844
- catch (e_6_1) { e_6 = { error: e_6_1 }; }
845
- finally {
846
- try {
847
- if (_o && !_o.done && (_f = _m.return)) _f.call(_m);
848
- }
849
- finally { if (e_6) throw e_6.error; }
850
- }
851
- } /* not else */
852
- if (format) {
853
- if (format === 'JSON') {
854
- // TODO: @deprecated remove
855
- commands_1.push("FORMAT JSON");
856
- }
857
- } /* not else */
858
- pipelineString += '\n\n';
859
- pipelineString += commands_1.map(function (command) { return "- ".concat(command); }).join('\n');
860
- pipelineString += '\n\n';
861
- pipelineString += '```' + contentLanguage;
862
- pipelineString += '\n';
863
- pipelineString += spaceTrim$1(content);
864
- // <- TODO: [main] !!! Escape
865
- // <- TODO: [๐Ÿง ] Some clear strategy how to spaceTrim the blocks
866
- pipelineString += '\n';
867
- pipelineString += '```';
868
- pipelineString += '\n\n';
869
- pipelineString += "`-> {".concat(resultingParameterName, "}`"); // <- TODO: [main] !!! If the parameter here has description, add it and use templateParameterJsonToString
870
- }
871
- }
872
- catch (e_3_1) { e_3 = { error: e_3_1 }; }
873
- finally {
874
- try {
875
- if (templates_1_1 && !templates_1_1.done && (_c = templates_1.return)) _c.call(templates_1);
876
- }
877
- finally { if (e_3) throw e_3.error; }
878
- }
879
- return pipelineString;
880
- }
881
- /**
882
- * @private internal utility of `pipelineJsonToString`
883
- */
884
- function templateParameterJsonToString(templateParameterJson) {
885
- var name = templateParameterJson.name, description = templateParameterJson.description;
886
- var parameterString = "{".concat(name, "}");
887
- if (description) {
888
- parameterString = "".concat(parameterString, " ").concat(description);
889
- }
890
- return parameterString;
891
- }
892
- /**
893
- * TODO: [๐Ÿ›‹] Implement new features and commands into `pipelineJsonToString` + `templateParameterJsonToString` , use `stringifyCommand`
894
- * TODO: [๐Ÿง ] Is there a way to auto-detect missing features in pipelineJsonToString
895
- * TODO: [๐Ÿ›] Maybe make some markdown builder
896
- * TODO: [๐Ÿ›] Escape all
897
- * TODO: [๐Ÿง ] Should be in generated .ptbk.md file GENERATOR_WARNING
898
- */
899
-
900
- /**
901
- * This error indicates that the promptbook in a markdown format cannot be parsed into a valid promptbook object
902
- *
903
- * @public exported from `@promptbook/core`
904
- */
905
- var ParseError = /** @class */ (function (_super) {
906
- __extends(ParseError, _super);
907
- function ParseError(message) {
908
- var _this = _super.call(this, message) || this;
909
- _this.name = 'ParseError';
910
- Object.setPrototypeOf(_this, ParseError.prototype);
911
- return _this;
912
- }
913
- return ParseError;
914
- }(Error));
915
- /**
916
- * TODO: Maybe split `ParseError` and `ApplyError`
917
- */
918
-
919
- /**
920
- * This error indicates that the promptbook object has valid syntax (=can be parsed) but contains logical errors (like circular dependencies)
921
- *
922
- * @public exported from `@promptbook/core`
923
- */
924
- var PipelineLogicError = /** @class */ (function (_super) {
925
- __extends(PipelineLogicError, _super);
926
- function PipelineLogicError(message) {
927
- var _this = _super.call(this, message) || this;
928
- _this.name = 'PipelineLogicError';
929
- Object.setPrototypeOf(_this, PipelineLogicError.prototype);
930
- return _this;
931
- }
932
- return PipelineLogicError;
933
- }(Error));
934
-
935
- /**
936
- * Tests if given string is valid semantic version
937
- *
938
- * Note: There are two simmilar functions:
939
- * - `isValidSemanticVersion` which tests any semantic version
940
- * - `isValidPromptbookVersion` *(this one)* which tests just Promptbook versions
941
- *
942
- * @public exported from `@promptbook/utils`
943
- */
944
- function isValidSemanticVersion(version) {
945
- if (typeof version !== 'string') {
946
- return false;
947
- }
948
- if (version.startsWith('0.0.0')) {
949
- return false;
950
- }
951
- return /^\d+\.\d+\.\d+(-\d+)?$/i.test(version);
952
- }
953
-
954
- /**
955
- * Tests if given string is valid promptbook version
956
- * It looks into list of known promptbook versions.
957
- *
958
- * @see https://www.npmjs.com/package/promptbook?activeTab=versions
959
- * 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.
960
- * Note: There are two simmilar functions:
961
- * - `isValidSemanticVersion` which tests any semantic version
962
- * - `isValidPromptbookVersion` *(this one)* which tests just Promptbook versions
963
- *
964
- * @public exported from `@promptbook/utils`
965
- */
966
- function isValidPromptbookVersion(version) {
967
- if (!isValidSemanticVersion(version)) {
968
- return false;
969
- }
970
- if ( /* version === '1.0.0' || */version === '2.0.0' || version === '3.0.0') {
971
- return false;
972
- }
973
- // <- TODO: [main] !!! Check isValidPromptbookVersion against PROMPTBOOK_VERSIONS
974
- return true;
975
- }
976
-
977
- /**
978
- * Checks if an URL is reserved for private networks or localhost.
979
- *
980
- * Note: There are two simmilar functions:
981
- * - `isUrlOnPrivateNetwork` which tests full URL
982
- * - `isHostnameOnPrivateNetwork` *(this one)* which tests just hostname
983
- *
984
- * @public exported from `@promptbook/utils`
985
- */
986
- function isHostnameOnPrivateNetwork(hostname) {
987
- if (hostname === 'example.com' ||
988
- hostname === 'localhost' ||
989
- hostname.endsWith('.localhost') ||
990
- hostname.endsWith('.local') ||
991
- hostname.endsWith('.test') ||
992
- hostname === '127.0.0.1' ||
993
- hostname === '::1') {
994
- return true;
995
- }
996
- if (hostname.includes(':')) {
997
- // IPv6
998
- var ipParts = hostname.split(':');
999
- return ipParts[0] === 'fc00' || ipParts[0] === 'fd00' || ipParts[0] === 'fe80';
1000
- }
1001
- else {
1002
- // IPv4
1003
- var ipParts = hostname.split('.').map(function (part) { return Number.parseInt(part, 10); });
1004
- return (ipParts[0] === 10 ||
1005
- (ipParts[0] === 172 && ipParts[1] >= 16 && ipParts[1] <= 31) ||
1006
- (ipParts[0] === 192 && ipParts[1] === 168));
1007
- }
1008
- }
1009
-
1010
- /**
1011
- * Checks if an IP address or hostname is reserved for private networks or localhost.
1012
- *
1013
- * Note: There are two simmilar functions:
1014
- * - `isUrlOnPrivateNetwork` *(this one)* which tests full URL
1015
- * - `isHostnameOnPrivateNetwork` which tests just hostname
1016
- *
1017
- * @param {string} ipAddress - The IP address to check.
1018
- * @returns {boolean} Returns true if the IP address is reserved for private networks or localhost, otherwise false.
1019
- * @public exported from `@promptbook/utils`
1020
- */
1021
- function isUrlOnPrivateNetwork(url) {
1022
- if (typeof url === 'string') {
1023
- url = new URL(url);
1024
- }
1025
- return isHostnameOnPrivateNetwork(url.hostname);
1026
- }
1027
-
1028
- /**
1029
- * Tests if given string is valid URL.
1030
- *
1031
- * Note: Dataurl are considered perfectly valid.
1032
- * Note: There are two simmilar functions:
1033
- * - `isValidUrl` which tests any URL
1034
- * - `isValidPipelineUrl` *(this one)* which tests just promptbook URL
1035
- *
1036
- * @public exported from `@promptbook/utils`
1037
- */
1038
- function isValidUrl(url) {
1039
- if (typeof url !== 'string') {
1040
- return false;
1041
- }
1042
- try {
1043
- if (url.startsWith('blob:')) {
1044
- url = url.replace(/^blob:/, '');
1045
- }
1046
- var urlObject = new URL(url /* because fail is handled */);
1047
- if (!['http:', 'https:', 'data:'].includes(urlObject.protocol)) {
1048
- return false;
1049
- }
1050
- return true;
1051
- }
1052
- catch (error) {
1053
- return false;
744
+ catch (error) {
745
+ return false;
1054
746
  }
1055
747
  }
1056
748
 
749
+ var defaultDiacriticsRemovalMap = [
750
+ {
751
+ base: 'A',
752
+ 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',
753
+ },
754
+ { base: 'AA', letters: '\uA732' },
755
+ { base: 'AE', letters: '\u00C6\u01FC\u01E2' },
756
+ { base: 'AO', letters: '\uA734' },
757
+ { base: 'AU', letters: '\uA736' },
758
+ { base: 'AV', letters: '\uA738\uA73A' },
759
+ { base: 'AY', letters: '\uA73C' },
760
+ {
761
+ base: 'B',
762
+ letters: '\u0042\u24B7\uFF22\u1E02\u1E04\u1E06\u0243\u0182\u0181',
763
+ },
764
+ {
765
+ base: 'C',
766
+ letters: '\u0043\u24B8\uFF23\u0106\u0108\u010A\u010C\u00C7\u1E08\u0187\u023B\uA73E',
767
+ },
768
+ {
769
+ base: 'D',
770
+ letters: '\u0044\u24B9\uFF24\u1E0A\u010E\u1E0C\u1E10\u1E12\u1E0E\u0110\u018B\u018A\u0189\uA779\u00D0',
771
+ },
772
+ { base: 'DZ', letters: '\u01F1\u01C4' },
773
+ { base: 'Dz', letters: '\u01F2\u01C5' },
774
+ {
775
+ base: 'E',
776
+ 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',
777
+ },
778
+ { base: 'F', letters: '\u0046\u24BB\uFF26\u1E1E\u0191\uA77B' },
779
+ {
780
+ base: 'G',
781
+ letters: '\u0047\u24BC\uFF27\u01F4\u011C\u1E20\u011E\u0120\u01E6\u0122\u01E4\u0193\uA7A0\uA77D\uA77E',
782
+ },
783
+ {
784
+ base: 'H',
785
+ letters: '\u0048\u24BD\uFF28\u0124\u1E22\u1E26\u021E\u1E24\u1E28\u1E2A\u0126\u2C67\u2C75\uA78D',
786
+ },
787
+ {
788
+ base: 'I',
789
+ letters: '\u0049\u24BE\uFF29\u00CC\u00CD\u00CE\u0128\u012A\u012C\u0130\u00CF\u1E2E\u1EC8\u01CF\u0208\u020A\u1ECA\u012E\u1E2C\u0197',
790
+ },
791
+ { base: 'J', letters: '\u004A\u24BF\uFF2A\u0134\u0248' },
792
+ {
793
+ base: 'K',
794
+ letters: '\u004B\u24C0\uFF2B\u1E30\u01E8\u1E32\u0136\u1E34\u0198\u2C69\uA740\uA742\uA744\uA7A2',
795
+ },
796
+ {
797
+ base: 'L',
798
+ letters: '\u004C\u24C1\uFF2C\u013F\u0139\u013D\u1E36\u1E38\u013B\u1E3C\u1E3A\u0141\u023D\u2C62\u2C60\uA748\uA746\uA780',
799
+ },
800
+ { base: 'LJ', letters: '\u01C7' },
801
+ { base: 'Lj', letters: '\u01C8' },
802
+ { base: 'M', letters: '\u004D\u24C2\uFF2D\u1E3E\u1E40\u1E42\u2C6E\u019C' },
803
+ {
804
+ base: 'N',
805
+ letters: '\u004E\u24C3\uFF2E\u01F8\u0143\u00D1\u1E44\u0147\u1E46\u0145\u1E4A\u1E48\u0220\u019D\uA790\uA7A4',
806
+ },
807
+ { base: 'NJ', letters: '\u01CA' },
808
+ { base: 'Nj', letters: '\u01CB' },
809
+ {
810
+ base: 'O',
811
+ 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',
812
+ },
813
+ { base: 'OI', letters: '\u01A2' },
814
+ { base: 'OO', letters: '\uA74E' },
815
+ { base: 'OU', letters: '\u0222' },
816
+ { base: 'OE', letters: '\u008C\u0152' },
817
+ { base: 'oe', letters: '\u009C\u0153' },
818
+ {
819
+ base: 'P',
820
+ letters: '\u0050\u24C5\uFF30\u1E54\u1E56\u01A4\u2C63\uA750\uA752\uA754',
821
+ },
822
+ { base: 'Q', letters: '\u0051\u24C6\uFF31\uA756\uA758\u024A' },
823
+ {
824
+ base: 'R',
825
+ letters: '\u0052\u24C7\uFF32\u0154\u1E58\u0158\u0210\u0212\u1E5A\u1E5C\u0156\u1E5E\u024C\u2C64\uA75A\uA7A6\uA782',
826
+ },
827
+ {
828
+ base: 'S',
829
+ letters: '\u0053\u24C8\uFF33\u1E9E\u015A\u1E64\u015C\u1E60\u0160\u1E66\u1E62\u1E68\u0218\u015E\u2C7E\uA7A8\uA784',
830
+ },
831
+ {
832
+ base: 'T',
833
+ letters: '\u0054\u24C9\uFF34\u1E6A\u0164\u1E6C\u021A\u0162\u1E70\u1E6E\u0166\u01AC\u01AE\u023E\uA786',
834
+ },
835
+ { base: 'TZ', letters: '\uA728' },
836
+ {
837
+ base: 'U',
838
+ 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',
839
+ },
840
+ { base: 'V', letters: '\u0056\u24CB\uFF36\u1E7C\u1E7E\u01B2\uA75E\u0245' },
841
+ { base: 'VY', letters: '\uA760' },
842
+ {
843
+ base: 'W',
844
+ letters: '\u0057\u24CC\uFF37\u1E80\u1E82\u0174\u1E86\u1E84\u1E88\u2C72',
845
+ },
846
+ { base: 'X', letters: '\u0058\u24CD\uFF38\u1E8A\u1E8C' },
847
+ {
848
+ base: 'Y',
849
+ letters: '\u0059\u24CE\uFF39\u1EF2\u00DD\u0176\u1EF8\u0232\u1E8E\u0178\u1EF6\u1EF4\u01B3\u024E\u1EFE',
850
+ },
851
+ {
852
+ base: 'Z',
853
+ letters: '\u005A\u24CF\uFF3A\u0179\u1E90\u017B\u017D\u1E92\u1E94\u01B5\u0224\u2C7F\u2C6B\uA762',
854
+ },
855
+ {
856
+ base: 'a',
857
+ 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',
858
+ },
859
+ { base: 'aa', letters: '\uA733' },
860
+ { base: 'ae', letters: '\u00E6\u01FD\u01E3' },
861
+ { base: 'ao', letters: '\uA735' },
862
+ { base: 'au', letters: '\uA737' },
863
+ { base: 'av', letters: '\uA739\uA73B' },
864
+ { base: 'ay', letters: '\uA73D' },
865
+ {
866
+ base: 'b',
867
+ letters: '\u0062\u24D1\uFF42\u1E03\u1E05\u1E07\u0180\u0183\u0253',
868
+ },
869
+ {
870
+ base: 'c',
871
+ letters: '\u0063\u24D2\uFF43\u0107\u0109\u010B\u010D\u00E7\u1E09\u0188\u023C\uA73F\u2184',
872
+ },
873
+ {
874
+ base: 'd',
875
+ letters: '\u0064\u24D3\uFF44\u1E0B\u010F\u1E0D\u1E11\u1E13\u1E0F\u0111\u018C\u0256\u0257\uA77A',
876
+ },
877
+ { base: 'dz', letters: '\u01F3\u01C6' },
878
+ {
879
+ base: 'e',
880
+ 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',
881
+ },
882
+ { base: 'f', letters: '\u0066\u24D5\uFF46\u1E1F\u0192\uA77C' },
883
+ {
884
+ base: 'g',
885
+ letters: '\u0067\u24D6\uFF47\u01F5\u011D\u1E21\u011F\u0121\u01E7\u0123\u01E5\u0260\uA7A1\u1D79\uA77F',
886
+ },
887
+ {
888
+ base: 'h',
889
+ letters: '\u0068\u24D7\uFF48\u0125\u1E23\u1E27\u021F\u1E25\u1E29\u1E2B\u1E96\u0127\u2C68\u2C76\u0265',
890
+ },
891
+ { base: 'hv', letters: '\u0195' },
892
+ {
893
+ base: 'i',
894
+ letters: '\u0069\u24D8\uFF49\u00EC\u00ED\u00EE\u0129\u012B\u012D\u00EF\u1E2F\u1EC9\u01D0\u0209\u020B\u1ECB\u012F\u1E2D\u0268\u0131',
895
+ },
896
+ { base: 'j', letters: '\u006A\u24D9\uFF4A\u0135\u01F0\u0249' },
897
+ {
898
+ base: 'k',
899
+ letters: '\u006B\u24DA\uFF4B\u1E31\u01E9\u1E33\u0137\u1E35\u0199\u2C6A\uA741\uA743\uA745\uA7A3',
900
+ },
901
+ {
902
+ base: 'l',
903
+ letters: '\u006C\u24DB\uFF4C\u0140\u013A\u013E\u1E37\u1E39\u013C\u1E3D\u1E3B\u017F\u0142\u019A\u026B\u2C61\uA749\uA781\uA747',
904
+ },
905
+ { base: 'lj', letters: '\u01C9' },
906
+ { base: 'm', letters: '\u006D\u24DC\uFF4D\u1E3F\u1E41\u1E43\u0271\u026F' },
907
+ {
908
+ base: 'n',
909
+ letters: '\u006E\u24DD\uFF4E\u01F9\u0144\u00F1\u1E45\u0148\u1E47\u0146\u1E4B\u1E49\u019E\u0272\u0149\uA791\uA7A5',
910
+ },
911
+ { base: 'nj', letters: '\u01CC' },
912
+ {
913
+ base: 'o',
914
+ 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',
915
+ },
916
+ { base: 'oi', letters: '\u01A3' },
917
+ { base: 'ou', letters: '\u0223' },
918
+ { base: 'oo', letters: '\uA74F' },
919
+ {
920
+ base: 'p',
921
+ letters: '\u0070\u24DF\uFF50\u1E55\u1E57\u01A5\u1D7D\uA751\uA753\uA755',
922
+ },
923
+ { base: 'q', letters: '\u0071\u24E0\uFF51\u024B\uA757\uA759' },
924
+ {
925
+ base: 'r',
926
+ letters: '\u0072\u24E1\uFF52\u0155\u1E59\u0159\u0211\u0213\u1E5B\u1E5D\u0157\u1E5F\u024D\u027D\uA75B\uA7A7\uA783',
927
+ },
928
+ {
929
+ base: 's',
930
+ letters: '\u0073\u24E2\uFF53\u00DF\u015B\u1E65\u015D\u1E61\u0161\u1E67\u1E63\u1E69\u0219\u015F\u023F\uA7A9\uA785\u1E9B',
931
+ },
932
+ {
933
+ base: 't',
934
+ letters: '\u0074\u24E3\uFF54\u1E6B\u1E97\u0165\u1E6D\u021B\u0163\u1E71\u1E6F\u0167\u01AD\u0288\u2C66\uA787',
935
+ },
936
+ { base: 'tz', letters: '\uA729' },
937
+ {
938
+ base: 'u',
939
+ 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',
940
+ },
941
+ { base: 'v', letters: '\u0076\u24E5\uFF56\u1E7D\u1E7F\u028B\uA75F\u028C' },
942
+ { base: 'vy', letters: '\uA761' },
943
+ {
944
+ base: 'w',
945
+ letters: '\u0077\u24E6\uFF57\u1E81\u1E83\u0175\u1E87\u1E85\u1E98\u1E89\u2C73',
946
+ },
947
+ { base: 'x', letters: '\u0078\u24E7\uFF58\u1E8B\u1E8D' },
948
+ {
949
+ base: 'y',
950
+ letters: '\u0079\u24E8\uFF59\u1EF3\u00FD\u0177\u1EF9\u0233\u1E8F\u00FF\u1EF7\u1E99\u1EF5\u01B4\u024F\u1EFF',
951
+ },
952
+ {
953
+ base: 'z',
954
+ letters: '\u007A\u24E9\uFF5A\u017A\u1E91\u017C\u017E\u1E93\u1E95\u01B6\u0225\u0240\u2C6C\uA763',
955
+ },
956
+ ];
1057
957
  /**
1058
- * Tests if given string is valid pipeline URL URL.
958
+ * Map of letters from diacritic variant to diacritless variant
959
+ * Contains lowercase and uppercase separatelly
1059
960
  *
1060
- * Note: There are two simmilar functions:
1061
- * - `isValidUrl` which tests any URL
1062
- * - `isValidPipelineUrl` *(this one)* which tests just pipeline URL
961
+ * > "รก" => "a"
962
+ * > "ฤ›" => "e"
963
+ * > "ฤ‚" => "A"
964
+ * > ...
1063
965
  *
1064
966
  * @public exported from `@promptbook/utils`
1065
967
  */
1066
- function isValidPipelineUrl(url) {
1067
- if (!isValidUrl(url)) {
1068
- return false;
1069
- }
1070
- if (!url.startsWith('https://')) {
1071
- return false;
1072
- }
1073
- if (!url.endsWith('.ptbk.md')) {
1074
- return false;
1075
- }
1076
- if (url.includes('#')) {
1077
- // TODO: [๐Ÿ ]
1078
- return false;
1079
- }
1080
- if (isUrlOnPrivateNetwork(url)) {
1081
- return false;
968
+ var DIACRITIC_VARIANTS_LETTERS = {};
969
+ // tslint:disable-next-line: prefer-for-of
970
+ for (var i = 0; i < defaultDiacriticsRemovalMap.length; i++) {
971
+ var letters = defaultDiacriticsRemovalMap[i].letters;
972
+ // tslint:disable-next-line: prefer-for-of
973
+ for (var j = 0; j < letters.length; j++) {
974
+ DIACRITIC_VARIANTS_LETTERS[letters[j]] = defaultDiacriticsRemovalMap[i].base;
1082
975
  }
1083
- return true;
1084
976
  }
1085
- /**
1086
- * TODO: [๐Ÿ ] Maybe more info why the URL is invalid
1087
- */
977
+ // <- TODO: [๐Ÿ“] Put to maker function to save execution time if not needed
978
+ /*
979
+ @see https://stackoverflow.com/questions/990904/remove-accents-diacritics-in-a-string-in-javascript
980
+ Licensed under the Apache License, Version 2.0 (the "License");
981
+ you may not use this file except in compliance with the License.
982
+ You may obtain a copy of the License at
983
+
984
+ http://www.apache.org/licenses/LICENSE-2.0
985
+
986
+ Unless required by applicable law or agreed to in writing, software
987
+ distributed under the License is distributed on an "AS IS" BASIS,
988
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
989
+ See the License for the specific language governing permissions and
990
+ limitations under the License.
991
+ */
1088
992
 
1089
993
  /**
1090
- * Validates PipelineJson if it is logically valid
1091
- *
1092
- * It checks:
1093
- * - if it has correct parameters dependency
1094
- *
1095
- * It does NOT check:
1096
- * - if it is valid json
1097
- * - if it is meaningful
994
+ * @@@
1098
995
  *
1099
- * @param pipeline valid or invalid PipelineJson
1100
- * @returns the same pipeline if it is logically valid
1101
- * @throws {PipelineLogicError} on logical error in the pipeline
1102
- * @public exported from `@promptbook/core`
996
+ * @param input @@@
997
+ * @returns @@@
998
+ * @public exported from `@promptbook/utils`
1103
999
  */
1104
- function validatePipeline(pipeline) {
1105
- if (IS_PIPELINE_LOGIC_VALIDATED) {
1106
- validatePipelineCore(pipeline);
1107
- }
1108
- else {
1109
- try {
1110
- validatePipelineCore(pipeline);
1111
- }
1112
- catch (error) {
1113
- if (!(error instanceof PipelineLogicError)) {
1114
- throw error;
1115
- }
1116
- console.error(spaceTrim(function (block) { return "\n Pipeline is not valid but logic errors are temporarily disabled via `IS_PIPELINE_LOGIC_VALIDATED`\n\n ".concat(block(error.message), "\n "); }));
1117
- }
1118
- }
1119
- return pipeline;
1000
+ function removeDiacritics(input) {
1001
+ /*eslint no-control-regex: "off"*/
1002
+ return input.replace(/[^\u0000-\u007E]/g, function (a) {
1003
+ return DIACRITIC_VARIANTS_LETTERS[a] || a;
1004
+ });
1120
1005
  }
1121
1006
  /**
1122
- * @private internal function for `validatePipeline`
1007
+ * TODO: [ะ–] Variant for cyrillic (and in general non-latin) letters
1123
1008
  */
1124
- function validatePipelineCore(pipeline) {
1125
- // TODO: [๐Ÿง ] Maybe test if promptbook is a promise and make specific error case for that
1126
- var e_1, _a, e_2, _b, e_3, _c;
1127
- var pipelineIdentification = (function () {
1128
- // Note: This is a ๐Ÿ˜ implementation of [๐Ÿšž]
1129
- var _ = [];
1130
- if (pipeline.sourceFile !== undefined) {
1131
- _.push("File: ".concat(pipeline.sourceFile));
1132
- }
1133
- if (pipeline.pipelineUrl !== undefined) {
1134
- _.push("Url: ".concat(pipeline.pipelineUrl));
1135
- }
1136
- return _.join('\n');
1137
- })();
1138
- if (pipeline.pipelineUrl !== undefined && !isValidPipelineUrl(pipeline.pipelineUrl)) {
1139
- // <- Note: [๐Ÿšฒ]
1140
- throw new PipelineLogicError(spaceTrim(function (block) { return "\n Invalid promptbook URL \"".concat(pipeline.pipelineUrl, "\"\n\n ").concat(block(pipelineIdentification), "\n "); }));
1141
- }
1142
- if (pipeline.promptbookVersion !== undefined && !isValidPromptbookVersion(pipeline.promptbookVersion)) {
1143
- // <- Note: [๐Ÿšฒ]
1144
- throw new PipelineLogicError(spaceTrim(function (block) { return "\n Invalid Promptbook Version \"".concat(pipeline.promptbookVersion, "\"\n\n ").concat(block(pipelineIdentification), "\n "); }));
1145
- }
1146
- // TODO: [๐Ÿง ] Maybe do here some propper JSON-schema / ZOD checking
1147
- if (!Array.isArray(pipeline.parameters)) {
1148
- // TODO: [๐Ÿง ] what is the correct error tp throw - maybe PromptbookSchemaError
1149
- throw new ParseError(spaceTrim(function (block) { return "\n Pipeline is valid JSON but with wrong structure\n\n `PipelineJson.parameters` expected to be an array, but got ".concat(typeof pipeline.parameters, "\n\n ").concat(block(pipelineIdentification), "\n "); }));
1150
- }
1151
- // TODO: [๐Ÿง ] Maybe do here some propper JSON-schema / ZOD checking
1152
- if (!Array.isArray(pipeline.templates)) {
1153
- // TODO: [๐Ÿง ] what is the correct error tp throw - maybe PromptbookSchemaError
1154
- throw new ParseError(spaceTrim(function (block) { return "\n Pipeline is valid JSON but with wrong structure\n\n `PipelineJson.templates` expected to be an array, but got ".concat(typeof pipeline.templates, "\n\n ").concat(block(pipelineIdentification), "\n "); }));
1155
- }
1156
- var _loop_1 = function (parameter) {
1157
- if (parameter.isInput && parameter.isOutput) {
1158
- throw new PipelineLogicError(spaceTrim(function (block) { return "\n\n Parameter {".concat(parameter.name, "} can not be both input and output\n\n ").concat(block(pipelineIdentification), "\n "); }));
1159
- }
1160
- // Note: Testing that parameter is either intermediate or output BUT not created and unused
1161
- if (!parameter.isInput &&
1162
- !parameter.isOutput &&
1163
- !pipeline.templates.some(function (template) { return template.dependentParameterNames.includes(parameter.name); })) {
1164
- throw new PipelineLogicError(spaceTrim(function (block) { return "\n Parameter {".concat(parameter.name, "} is created but not used\n\n You can declare {").concat(parameter.name, "} as output parameter by adding in the header:\n - OUTPUT PARAMETER `{").concat(parameter.name, "}` ").concat(parameter.description || '', "\n\n ").concat(block(pipelineIdentification), "\n\n "); }));
1165
- }
1166
- // Note: Testing that parameter is either input or result of some template
1167
- if (!parameter.isInput &&
1168
- !pipeline.templates.some(function (template) { return template.resultingParameterName === parameter.name; })) {
1169
- throw new PipelineLogicError(spaceTrim(function (block) { return "\n Parameter {".concat(parameter.name, "} is declared but not defined\n\n You can do one of these:\n 1) Remove declaration of {").concat(parameter.name, "}\n 2) Add template that results in -> {").concat(parameter.name, "}\n\n ").concat(block(pipelineIdentification), "\n "); }));
1170
- }
1171
- };
1172
- try {
1173
- // Note: Check each parameter individually
1174
- for (var _d = __values(pipeline.parameters), _e = _d.next(); !_e.done; _e = _d.next()) {
1175
- var parameter = _e.value;
1176
- _loop_1(parameter);
1177
- }
1178
- }
1179
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
1180
- finally {
1181
- try {
1182
- if (_e && !_e.done && (_a = _d.return)) _a.call(_d);
1183
- }
1184
- finally { if (e_1) throw e_1.error; }
1185
- }
1186
- // Note: All input parameters are defined - so that they can be used as result of some template
1187
- var definedParameters = new Set(pipeline.parameters.filter(function (_a) {
1188
- var isInput = _a.isInput;
1189
- return isInput;
1190
- }).map(function (_a) {
1191
- var name = _a.name;
1192
- return name;
1193
- }));
1194
- var _loop_2 = function (template) {
1195
- var e_4, _h, e_5, _j;
1196
- if (definedParameters.has(template.resultingParameterName)) {
1197
- throw new PipelineLogicError(spaceTrim(function (block) { return "\n Parameter {".concat(template.resultingParameterName, "} is defined multiple times\n\n ").concat(block(pipelineIdentification), "\n "); }));
1198
- }
1199
- if (RESERVED_PARAMETER_NAMES.includes(template.resultingParameterName)) {
1200
- throw new PipelineLogicError(spaceTrim(function (block) { return "\n Parameter name {".concat(template.resultingParameterName, "} is reserved, please use different name\n\n ").concat(block(pipelineIdentification), "\n "); }));
1201
- }
1202
- definedParameters.add(template.resultingParameterName);
1203
- if (template.jokerParameterNames && template.jokerParameterNames.length > 0) {
1204
- if (!template.format &&
1205
- !template.expectations /* <- TODO: Require at least 1 -> min <- expectation to use jokers */) {
1206
- throw new PipelineLogicError(spaceTrim(function (block) { return "\n Joker parameters are used for {".concat(template.resultingParameterName, "} but no expectations are defined\n\n ").concat(block(pipelineIdentification), "\n "); }));
1207
- }
1208
- var _loop_4 = function (joker) {
1209
- if (!template.dependentParameterNames.includes(joker)) {
1210
- throw new PipelineLogicError(spaceTrim(function (block) { return "\n Parameter {".concat(joker, "} is used for {").concat(template.resultingParameterName, "} as joker but not in `dependentParameterNames`\n\n ").concat(block(pipelineIdentification), "\n "); }));
1211
- }
1212
- };
1213
- try {
1214
- for (var _k = (e_4 = void 0, __values(template.jokerParameterNames)), _l = _k.next(); !_l.done; _l = _k.next()) {
1215
- var joker = _l.value;
1216
- _loop_4(joker);
1217
- }
1218
- }
1219
- catch (e_4_1) { e_4 = { error: e_4_1 }; }
1220
- finally {
1221
- try {
1222
- if (_l && !_l.done && (_h = _k.return)) _h.call(_k);
1223
- }
1224
- finally { if (e_4) throw e_4.error; }
1225
- }
1226
- }
1227
- if (template.expectations) {
1228
- var _loop_5 = function (unit, min, max) {
1229
- if (min !== undefined && max !== undefined && min > max) {
1230
- throw new PipelineLogicError(spaceTrim(function (block) { return "\n Min expectation (=".concat(min, ") of ").concat(unit, " is higher than max expectation (=").concat(max, ")\n\n ").concat(block(pipelineIdentification), "\n "); }));
1231
- }
1232
- if (min !== undefined && min < 0) {
1233
- throw new PipelineLogicError(spaceTrim(function (block) { return "\n Min expectation of ".concat(unit, " must be zero or positive\n\n ").concat(block(pipelineIdentification), "\n "); }));
1234
- }
1235
- if (max !== undefined && max <= 0) {
1236
- throw new PipelineLogicError(spaceTrim(function (block) { return "\n Max expectation of ".concat(unit, " must be positive\n\n ").concat(block(pipelineIdentification), "\n "); }));
1237
- }
1238
- };
1239
- try {
1240
- for (var _m = (e_5 = void 0, __values(Object.entries(template.expectations))), _o = _m.next(); !_o.done; _o = _m.next()) {
1241
- var _p = __read(_o.value, 2), unit = _p[0], _q = _p[1], min = _q.min, max = _q.max;
1242
- _loop_5(unit, min, max);
1243
- }
1244
- }
1245
- catch (e_5_1) { e_5 = { error: e_5_1 }; }
1246
- finally {
1247
- try {
1248
- if (_o && !_o.done && (_j = _m.return)) _j.call(_m);
1249
- }
1250
- finally { if (e_5) throw e_5.error; }
1251
- }
1252
- }
1253
- };
1254
- try {
1255
- // Note: Checking each template individually
1256
- for (var _f = __values(pipeline.templates), _g = _f.next(); !_g.done; _g = _f.next()) {
1257
- var template = _g.value;
1258
- _loop_2(template);
1259
- }
1260
- }
1261
- catch (e_2_1) { e_2 = { error: e_2_1 }; }
1262
- finally {
1263
- try {
1264
- if (_g && !_g.done && (_b = _f.return)) _b.call(_f);
1265
- }
1266
- finally { if (e_2) throw e_2.error; }
1267
- }
1268
- // Note: Detect circular dependencies
1269
- var resovedParameters = pipeline.parameters
1270
- .filter(function (_a) {
1271
- var isInput = _a.isInput;
1272
- return isInput;
1273
- })
1274
- .map(function (_a) {
1275
- var name = _a.name;
1276
- return name;
1277
- });
1009
+
1010
+ /**
1011
+ * @@@
1012
+ *
1013
+ * @param text @@@
1014
+ * @returns @@@
1015
+ * @example 'hello-world'
1016
+ * @example 'i-love-promptbook'
1017
+ * @public exported from `@promptbook/utils`
1018
+ */
1019
+ function normalizeToKebabCase(text) {
1020
+ var e_1, _a;
1021
+ text = removeDiacritics(text);
1022
+ var charType;
1023
+ var lastCharType = 'OTHER';
1024
+ var normalizedName = '';
1278
1025
  try {
1279
- // Note: All reserved parameters are resolved
1280
- for (var RESERVED_PARAMETER_NAMES_1 = __values(RESERVED_PARAMETER_NAMES), RESERVED_PARAMETER_NAMES_1_1 = RESERVED_PARAMETER_NAMES_1.next(); !RESERVED_PARAMETER_NAMES_1_1.done; RESERVED_PARAMETER_NAMES_1_1 = RESERVED_PARAMETER_NAMES_1.next()) {
1281
- var reservedParameterName = RESERVED_PARAMETER_NAMES_1_1.value;
1282
- resovedParameters = __spreadArray(__spreadArray([], __read(resovedParameters), false), [reservedParameterName], false);
1026
+ for (var text_1 = __values(text), text_1_1 = text_1.next(); !text_1_1.done; text_1_1 = text_1.next()) {
1027
+ var char = text_1_1.value;
1028
+ var normalizedChar = void 0;
1029
+ if (/^[a-z]$/.test(char)) {
1030
+ charType = 'LOWERCASE';
1031
+ normalizedChar = char;
1032
+ }
1033
+ else if (/^[A-Z]$/.test(char)) {
1034
+ charType = 'UPPERCASE';
1035
+ normalizedChar = char.toLowerCase();
1036
+ }
1037
+ else if (/^[0-9]$/.test(char)) {
1038
+ charType = 'NUMBER';
1039
+ normalizedChar = char;
1040
+ }
1041
+ else {
1042
+ charType = 'OTHER';
1043
+ normalizedChar = '-';
1044
+ }
1045
+ if (charType !== lastCharType &&
1046
+ !(lastCharType === 'UPPERCASE' && charType === 'LOWERCASE') &&
1047
+ !(lastCharType === 'NUMBER') &&
1048
+ !(charType === 'NUMBER')) {
1049
+ normalizedName += '-';
1050
+ }
1051
+ normalizedName += normalizedChar;
1052
+ lastCharType = charType;
1283
1053
  }
1284
1054
  }
1285
- catch (e_3_1) { e_3 = { error: e_3_1 }; }
1055
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
1286
1056
  finally {
1287
1057
  try {
1288
- if (RESERVED_PARAMETER_NAMES_1_1 && !RESERVED_PARAMETER_NAMES_1_1.done && (_c = RESERVED_PARAMETER_NAMES_1.return)) _c.call(RESERVED_PARAMETER_NAMES_1);
1289
- }
1290
- finally { if (e_3) throw e_3.error; }
1291
- }
1292
- var unresovedTemplates = __spreadArray([], __read(pipeline.templates), false);
1293
- var loopLimit = LOOP_LIMIT;
1294
- var _loop_3 = function () {
1295
- if (loopLimit-- < 0) {
1296
- // Note: Really UnexpectedError not LimitReachedError - this should not happen and be caught below
1297
- throw new UnexpectedError(spaceTrim(function (block) { return "\n Loop limit reached during detection of circular dependencies in `validatePipeline`\n\n ".concat(block(pipelineIdentification), "\n "); }));
1298
- }
1299
- var currentlyResovedTemplates = unresovedTemplates.filter(function (template) {
1300
- return template.dependentParameterNames.every(function (name) { return resovedParameters.includes(name); });
1301
- });
1302
- if (currentlyResovedTemplates.length === 0) {
1303
- throw new PipelineLogicError(
1304
- // TODO: [๐ŸŽ] DRY
1305
- spaceTrim(function (block) { return "\n\n Can not resolve some parameters:\n Either you are using a parameter that is not defined, or there are some circular dependencies.\n\n ".concat(block(pipelineIdentification), "\n\n Can not resolve:\n ").concat(block(unresovedTemplates
1306
- .map(function (_a) {
1307
- var resultingParameterName = _a.resultingParameterName, dependentParameterNames = _a.dependentParameterNames;
1308
- return "- Parameter {".concat(resultingParameterName, "} which depends on ").concat(dependentParameterNames
1309
- .map(function (dependentParameterName) { return "{".concat(dependentParameterName, "}"); })
1310
- .join(' and '));
1311
- })
1312
- .join('\n')), "\n\n Resolved:\n ").concat(block(resovedParameters.map(function (name) { return "- Parameter {".concat(name, "}"); }).join('\n')), "\n\n\n "); }));
1058
+ if (text_1_1 && !text_1_1.done && (_a = text_1.return)) _a.call(text_1);
1313
1059
  }
1314
- resovedParameters = __spreadArray(__spreadArray([], __read(resovedParameters), false), __read(currentlyResovedTemplates.map(function (_a) {
1315
- var resultingParameterName = _a.resultingParameterName;
1316
- return resultingParameterName;
1317
- })), false);
1318
- unresovedTemplates = unresovedTemplates.filter(function (template) { return !currentlyResovedTemplates.includes(template); });
1319
- };
1320
- while (unresovedTemplates.length > 0) {
1321
- _loop_3();
1060
+ finally { if (e_1) throw e_1.error; }
1322
1061
  }
1062
+ normalizedName = normalizedName.split(/-+/g).join('-');
1063
+ normalizedName = normalizedName.split(/-?\/-?/g).join('/');
1064
+ normalizedName = normalizedName.replace(/^-/, '');
1065
+ normalizedName = normalizedName.replace(/-$/, '');
1066
+ return normalizedName;
1323
1067
  }
1068
+
1324
1069
  /**
1325
- * TODO: !!!!! [๐Ÿงžโ€โ™€๏ธ] Do not allow joker + foreach
1326
- * TODO: [๐Ÿง ] Work with promptbookVersion
1327
- * TODO: Use here some json-schema, Zod or something similar and change it to:
1328
- * > /**
1329
- * > * Validates PipelineJson if it is logically valid.
1330
- * > *
1331
- * > * It checks:
1332
- * > * - it has a valid structure
1333
- * > * - ...
1334
- * > ex port function validatePipeline(promptbook: really_unknown): asserts promptbook is PipelineJson {
1070
+ * Removes emojis from a string and fix whitespaces
1071
+ *
1072
+ * @param text with emojis
1073
+ * @returns text without emojis
1074
+ * @public exported from `@promptbook/utils`
1335
1075
  */
1076
+ function removeEmojis(text) {
1077
+ // Replace emojis (and also ZWJ sequence) with hyphens
1078
+ text = text.replace(/(\p{Extended_Pictographic})\p{Modifier_Symbol}/gu, '$1');
1079
+ text = text.replace(/(\p{Extended_Pictographic})[\u{FE00}-\u{FE0F}]/gu, '$1');
1080
+ text = text.replace(/(\p{Extended_Pictographic})(\u{200D}\p{Extended_Pictographic})*/gu, '$1');
1081
+ text = text.replace(/\p{Extended_Pictographic}/gu, '');
1082
+ return text;
1083
+ }
1084
+
1336
1085
  /**
1337
- * TODO: [๐Ÿงณ][main] !!!! Validate that all samples match expectations
1338
- * TODO: [๐Ÿงณ][๐Ÿ][main] !!!! Validate that knowledge is valid (non-void)
1339
- * TODO: [๐Ÿงณ][main] !!!! Validate that persona can be used only with CHAT variant
1340
- * TODO: [๐Ÿงณ][main] !!!! Validate that parameter with reserved name not used RESERVED_PARAMETER_NAMES
1341
- * TODO: [๐Ÿงณ][main] !!!! Validate that reserved parameter is not used as joker
1342
- * TODO: [๐Ÿง ] Validation not only logic itself but imports around - files and websites and rerefenced pipelines exists
1343
- * TODO: [๐Ÿ› ] Actions, instruments (and maybe knowledge) => Functions and tools
1086
+ * Tests if given string is valid URL.
1087
+ *
1088
+ * Note: This does not check if the file exists only if the path is valid
1089
+ * @public exported from `@promptbook/utils`
1344
1090
  */
1091
+ function isValidFilePath(filename) {
1092
+ if (typeof filename !== 'string') {
1093
+ return false;
1094
+ }
1095
+ var filenameSlashes = filename.split('\\').join('/');
1096
+ // Absolute Unix path: /hello.txt
1097
+ if (/^(\/)/i.test(filenameSlashes)) {
1098
+ return true;
1099
+ }
1100
+ // Absolute Windows path: /hello.txt
1101
+ if (/^([A-Z]{1,2}:\/?)\//i.test(filenameSlashes)) {
1102
+ return true;
1103
+ }
1104
+ // Relative path: ./hello.txt
1105
+ if (/^(\.\.?\/)+/i.test(filenameSlashes)) {
1106
+ return true;
1107
+ }
1108
+ return false;
1109
+ }
1345
1110
 
1346
1111
  /**
1347
- * This error indicates that promptbook not found in the collection
1112
+ * @@@
1348
1113
  *
1349
- * @public exported from `@promptbook/core`
1114
+ * @param value @@@
1115
+ * @returns @@@
1116
+ * @example @@@
1117
+ * @public exported from `@promptbook/utils`
1350
1118
  */
1351
- var NotFoundError = /** @class */ (function (_super) {
1352
- __extends(NotFoundError, _super);
1353
- function NotFoundError(message) {
1354
- var _this = _super.call(this, message) || this;
1355
- _this.name = 'NotFoundError';
1356
- Object.setPrototypeOf(_this, NotFoundError.prototype);
1357
- return _this;
1119
+ function titleToName(value) {
1120
+ if (isValidUrl(value)) {
1121
+ value = value.replace(/^https?:\/\//, '');
1122
+ value = value.replace(/\.html$/, '');
1358
1123
  }
1359
- return NotFoundError;
1360
- }(Error));
1124
+ else if (isValidFilePath(value)) {
1125
+ value = basename(value);
1126
+ // Note: Keeping extension in the name
1127
+ }
1128
+ value = value.split('/').join('-');
1129
+ value = removeEmojis(value);
1130
+ value = normalizeToKebabCase(value);
1131
+ // TODO: [๐Ÿง ] Maybe warn or add some padding to short name which are not good identifiers
1132
+ return value;
1133
+ }
1361
1134
 
1362
1135
  /**
1363
- * This error indicates errors in referencing promptbooks between each other
1136
+ * @@@
1364
1137
  *
1365
- * @public exported from `@promptbook/core`
1138
+ * @private for `FileCacheStorage`
1366
1139
  */
1367
- var PipelineUrlError = /** @class */ (function (_super) {
1368
- __extends(PipelineUrlError, _super);
1369
- function PipelineUrlError(message) {
1370
- var _this = _super.call(this, message) || this;
1371
- _this.name = 'PipelineUrlError';
1372
- Object.setPrototypeOf(_this, PipelineUrlError.prototype);
1373
- return _this;
1374
- }
1375
- return PipelineUrlError;
1376
- }(Error));
1140
+ function nameToSubfolderPath(name) {
1141
+ return [name.substr(0, 1).toLowerCase(), name.substr(1, 1).toLowerCase()];
1142
+ }
1377
1143
 
1378
1144
  /**
1379
- * Parses the template and returns the list of all parameter names
1145
+ * Create a filename for intermediate cache for scrapers
1380
1146
  *
1381
- * @param template the template with parameters in {curly} braces
1382
- * @returns the list of parameter names
1383
- * @public exported from `@promptbook/utils`
1147
+ * Note: It also checks if directory exists and creates it if not
1148
+ *
1149
+ * @private as internal utility for scrapers
1384
1150
  */
1385
- function extractParameterNames(template) {
1386
- var e_1, _a;
1387
- var matches = template.matchAll(/{\w+}/g);
1388
- var parameterNames = new Set();
1151
+ function getScraperIntermediateSource(source, options) {
1152
+ return __awaiter(this, void 0, void 0, function () {
1153
+ var sourceFilename, url, rootDirname, cacheDirname, intermediateFilesStrategy, extension, isVerbose, hash, semanticName, pieces, name, cacheFilename, isDestroyed, fileHandler;
1154
+ return __generator(this, function (_a) {
1155
+ switch (_a.label) {
1156
+ case 0:
1157
+ sourceFilename = source.filename, url = source.url;
1158
+ rootDirname = options.rootDirname, cacheDirname = options.cacheDirname, intermediateFilesStrategy = options.intermediateFilesStrategy, extension = options.extension, isVerbose = options.isVerbose;
1159
+ hash = SHA256(
1160
+ // <- TODO: [๐Ÿฅฌ] Encapsulate sha256 to some private utility function
1161
+ hexEncoder.parse(sourceFilename || url || 'untitled'))
1162
+ .toString( /* hex */)
1163
+ .substring(0, 20);
1164
+ semanticName = normalizeToKebabCase(titleToName((sourceFilename || url || '').split('intermediate').join(''))).substring(0, 20);
1165
+ pieces = ['intermediate', semanticName, hash].filter(function (piece) { return piece !== ''; });
1166
+ name = pieces.join('-').split('--').join('-');
1167
+ // <- TODO: Use MAX_FILENAME_LENGTH
1168
+ TODO_USE(rootDirname); // <- TODO: [๐Ÿ˜ก]
1169
+ cacheFilename = join.apply(void 0, __spreadArray(__spreadArray([process.cwd(),
1170
+ cacheDirname], __read(nameToSubfolderPath(hash /* <- TODO: [๐ŸŽŽ] Maybe add some SHA256 prefix */)), false), [name], false)).split('\\')
1171
+ .join('/') +
1172
+ '.' +
1173
+ extension;
1174
+ return [4 /*yield*/, mkdir(dirname(cacheFilename), { recursive: true })];
1175
+ case 1:
1176
+ _a.sent();
1177
+ isDestroyed = true;
1178
+ fileHandler = {
1179
+ filename: cacheFilename,
1180
+ get isDestroyed() {
1181
+ return isDestroyed;
1182
+ },
1183
+ destroy: function () {
1184
+ return __awaiter(this, void 0, void 0, function () {
1185
+ return __generator(this, function (_a) {
1186
+ switch (_a.label) {
1187
+ case 0:
1188
+ if (!(intermediateFilesStrategy === 'HIDE_AND_CLEAN')) return [3 /*break*/, 2];
1189
+ if (isVerbose) {
1190
+ console.info('legacyDocumentScraper: Clening cache');
1191
+ }
1192
+ return [4 /*yield*/, rm(cacheFilename)];
1193
+ case 1:
1194
+ _a.sent();
1195
+ _a.label = 2;
1196
+ case 2:
1197
+ isDestroyed = true;
1198
+ return [2 /*return*/];
1199
+ }
1200
+ });
1201
+ });
1202
+ },
1203
+ };
1204
+ return [2 /*return*/, fileHandler];
1205
+ }
1206
+ });
1207
+ });
1208
+ }
1209
+ /**
1210
+ * Note: Not using `FileCacheStorage` for two reasons:
1211
+ * 1) Need to store more than serialized JSONs
1212
+ * 2) Need to switch between a `rootDirname` and `cacheDirname` <- TODO: [๐Ÿ˜ก]
1213
+ * TODO: [๐Ÿฑโ€๐Ÿ‰][๐Ÿง ] Make some smart crop
1214
+ * Note: [๐ŸŸข] Code in this file should never be never released in packages that could be imported into browser environment
1215
+ */
1216
+
1217
+ var PipelineCollection = [{title:"Prepare Knowledge from Markdown",pipelineUrl:"https://promptbook.studio/promptbook/prepare-knowledge-from-markdown.ptbk.md",parameters:[{name:"knowledgeContent",description:"Markdown document content",isInput:true,isOutput:false},{name:"knowledgePieces",description:"The knowledge JSON object",isInput:false,isOutput:true}],templates:[{templateType:"PROMPT_TEMPLATE",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:"./promptbook-collection/prepare-knowledge-from-markdown.ptbk.md"},{title:"Prepare Keywords",pipelineUrl:"https://promptbook.studio/promptbook/prepare-knowledge-keywords.ptbk.md",parameters:[{name:"knowledgePieceContent",description:"The content",isInput:true,isOutput:false},{name:"keywords",description:"Keywords separated by comma",isInput:false,isOutput:true}],templates:[{templateType:"PROMPT_TEMPLATE",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:"./promptbook-collection/prepare-knowledge-keywords.ptbk.md"},{title:"Prepare Title",pipelineUrl:"https://promptbook.studio/promptbook/prepare-knowledge-title.ptbk.md",parameters:[{name:"knowledgePieceContent",description:"The content",isInput:true,isOutput:false},{name:"title",description:"The title of the document",isInput:false,isOutput:true}],templates:[{templateType:"PROMPT_TEMPLATE",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:"./promptbook-collection/prepare-knowledge-title.ptbk.md"},{title:"Prepare Keywords",pipelineUrl:"https://promptbook.studio/promptbook/prepare-persona.ptbk.md",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}],templates:[{templateType:"PROMPT_TEMPLATE",name:"make-model-requirements",title:"Make modelRequirements",content:"You are experienced AI engineer, you need to create virtual assistant.\nWrite\n\n## Sample\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:"./promptbook-collection/prepare-persona.ptbk.md"}];
1218
+
1219
+ /**
1220
+ * Prettify the html code
1221
+ *
1222
+ * @param content raw html code
1223
+ * @returns formatted html code
1224
+ * @private withing the package because of HUGE size of prettier dependency
1225
+ */
1226
+ function prettifyMarkdown(content) {
1389
1227
  try {
1390
- for (var matches_1 = __values(matches), matches_1_1 = matches_1.next(); !matches_1_1.done; matches_1_1 = matches_1.next()) {
1391
- var match = matches_1_1.value;
1392
- var parameterName = match[0].slice(1, -1);
1393
- parameterNames.add(parameterName);
1394
- }
1228
+ return format(content, {
1229
+ parser: 'markdown',
1230
+ plugins: [parserHtml],
1231
+ // TODO: DRY - make some import or auto-copy of .prettierrc
1232
+ endOfLine: 'lf',
1233
+ tabWidth: 4,
1234
+ singleQuote: true,
1235
+ trailingComma: 'all',
1236
+ arrowParens: 'always',
1237
+ printWidth: 120,
1238
+ htmlWhitespaceSensitivity: 'ignore',
1239
+ jsxBracketSameLine: false,
1240
+ bracketSpacing: true,
1241
+ });
1395
1242
  }
1396
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
1397
- finally {
1398
- try {
1399
- if (matches_1_1 && !matches_1_1.done && (_a = matches_1.return)) _a.call(matches_1);
1400
- }
1401
- finally { if (e_1) throw e_1.error; }
1243
+ catch (error) {
1244
+ // TODO: [๐ŸŸฅ] Detect browser / node and make it colorfull
1245
+ console.error('There was an error with prettifying the markdown, using the original as the fallback', {
1246
+ error: error,
1247
+ html: content,
1248
+ });
1249
+ return content;
1402
1250
  }
1403
- return parameterNames;
1404
1251
  }
1405
1252
 
1406
1253
  /**
1407
- * Unprepare just strips the preparation data of the pipeline
1254
+ * Makes first letter of a string uppercase
1408
1255
  *
1409
- * @public exported from `@promptbook/core`
1256
+ * @public exported from `@promptbook/utils`
1410
1257
  */
1411
- function unpreparePipeline(pipeline) {
1412
- var personas = pipeline.personas, knowledgeSources = pipeline.knowledgeSources, templates = pipeline.templates;
1413
- personas = personas.map(function (persona) { return (__assign(__assign({}, persona), { modelRequirements: undefined, preparationIds: undefined })); });
1414
- knowledgeSources = knowledgeSources.map(function (knowledgeSource) { return (__assign(__assign({}, knowledgeSource), { preparationIds: undefined })); });
1415
- templates = templates.map(function (template) {
1416
- var dependentParameterNames = template.dependentParameterNames;
1417
- var parameterNames = extractParameterNames(template.preparedContent || '');
1418
- dependentParameterNames = dependentParameterNames.filter(function (dependentParameterName) { return !parameterNames.has(dependentParameterName); });
1419
- var templateUnprepared = __assign(__assign({}, template), { dependentParameterNames: dependentParameterNames });
1420
- delete templateUnprepared.preparedContent;
1421
- return templateUnprepared;
1422
- });
1423
- return $asDeeplyFrozenSerializableJson('Unprepared PipelineJson', __assign(__assign({}, pipeline), { templates: templates, knowledgeSources: knowledgeSources, knowledgePieces: [], personas: personas, preparations: [] }));
1258
+ function capitalize(word) {
1259
+ return word.substring(0, 1).toUpperCase() + word.substring(1);
1424
1260
  }
1425
- /**
1426
- * TODO: [๐Ÿงฟ] Maybe do same process with same granularity and subfinctions as `preparePipeline`
1427
- * TODO: Write tests for `preparePipeline`
1428
- * TODO: [๐Ÿ™] Make some standard order of json properties
1429
- */
1430
1261
 
1431
1262
  /**
1432
- * Library of pipelines that groups together pipelines for an application.
1433
- * This implementation is a very thin wrapper around the Array / Map of pipelines.
1263
+ * Converts promptbook in JSON format to string format
1434
1264
  *
1435
- * @private internal function of `createCollectionFromJson`, use `createCollectionFromJson` instead
1436
- * @see https://github.com/webgptorg/pipeline#pipeline-collection
1265
+ * @param pipelineJson Promptbook in JSON format (.ptbk.json)
1266
+ * @returns Promptbook in string format (.ptbk.md)
1267
+ * @public exported from `@promptbook/core`
1437
1268
  */
1438
- var SimplePipelineCollection = /** @class */ (function () {
1439
- /**
1440
- * Constructs a pipeline collection from pipelines
1441
- *
1442
- * @param pipelines @@@
1443
- *
1444
- * Note: During the construction logic of all pipelines are validated
1445
- * Note: It is not recommended to use this constructor directly, use `createCollectionFromJson` *(or other variant)* instead
1446
- */
1447
- function SimplePipelineCollection() {
1448
- var e_1, _a;
1449
- var pipelines = [];
1450
- for (var _i = 0; _i < arguments.length; _i++) {
1451
- pipelines[_i] = arguments[_i];
1269
+ function pipelineJsonToString(pipelineJson) {
1270
+ var e_1, _a, e_2, _b, e_3, _c, e_4, _d, e_5, _e, e_6, _f;
1271
+ var title = pipelineJson.title, pipelineUrl = pipelineJson.pipelineUrl, promptbookVersion = pipelineJson.promptbookVersion, description = pipelineJson.description, parameters = pipelineJson.parameters, templates = pipelineJson.templates;
1272
+ var pipelineString = "# ".concat(title);
1273
+ if (description) {
1274
+ pipelineString += '\n\n';
1275
+ pipelineString += description;
1276
+ }
1277
+ var commands = [];
1278
+ if (pipelineUrl) {
1279
+ commands.push("PIPELINE URL ".concat(pipelineUrl));
1280
+ }
1281
+ commands.push("PROMPTBOOK VERSION ".concat(promptbookVersion));
1282
+ // TODO: [main] !!! This increase size of the bundle and is probbably not necessary
1283
+ pipelineString = prettifyMarkdown(pipelineString);
1284
+ try {
1285
+ for (var _g = __values(parameters.filter(function (_a) {
1286
+ var isInput = _a.isInput;
1287
+ return isInput;
1288
+ })), _h = _g.next(); !_h.done; _h = _g.next()) {
1289
+ var parameter = _h.value;
1290
+ commands.push("INPUT PARAMETER ".concat(templateParameterJsonToString(parameter)));
1452
1291
  }
1453
- this.collection = new Map();
1292
+ }
1293
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
1294
+ finally {
1454
1295
  try {
1455
- for (var pipelines_1 = __values(pipelines), pipelines_1_1 = pipelines_1.next(); !pipelines_1_1.done; pipelines_1_1 = pipelines_1.next()) {
1456
- var pipeline = pipelines_1_1.value;
1457
- // TODO: [๐Ÿ‘ ] DRY
1458
- if (pipeline.pipelineUrl === undefined) {
1459
- throw new PipelineUrlError(spaceTrim("\n Pipeline with name \"".concat(pipeline.title, "\" does not have defined URL\n\n File:\n ").concat(pipeline.sourceFile || 'Unknown', "\n\n Note: Pipelines without URLs are called anonymous pipelines\n They can be used as standalone pipelines, but they cannot be referenced by other pipelines\n And also they cannot be used in the pipeline collection\n\n ")));
1296
+ if (_h && !_h.done && (_a = _g.return)) _a.call(_g);
1297
+ }
1298
+ finally { if (e_1) throw e_1.error; }
1299
+ }
1300
+ try {
1301
+ for (var _j = __values(parameters.filter(function (_a) {
1302
+ var isOutput = _a.isOutput;
1303
+ return isOutput;
1304
+ })), _k = _j.next(); !_k.done; _k = _j.next()) {
1305
+ var parameter = _k.value;
1306
+ commands.push("OUTPUT PARAMETER ".concat(templateParameterJsonToString(parameter)));
1307
+ }
1308
+ }
1309
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
1310
+ finally {
1311
+ try {
1312
+ if (_k && !_k.done && (_b = _j.return)) _b.call(_j);
1313
+ }
1314
+ finally { if (e_2) throw e_2.error; }
1315
+ }
1316
+ pipelineString += '\n\n';
1317
+ pipelineString += commands.map(function (command) { return "- ".concat(command); }).join('\n');
1318
+ try {
1319
+ for (var templates_1 = __values(templates), templates_1_1 = templates_1.next(); !templates_1_1.done; templates_1_1 = templates_1.next()) {
1320
+ var template = templates_1_1.value;
1321
+ var
1322
+ /* Note: Not using:> name, */
1323
+ title_1 = template.title, description_1 = template.description,
1324
+ /* Note: dependentParameterNames, */
1325
+ jokers = template.jokerParameterNames, templateType = template.templateType, content = template.content, postprocessing = template.postprocessingFunctionNames, expectations = template.expectations, format = template.format, resultingParameterName = template.resultingParameterName;
1326
+ pipelineString += '\n\n';
1327
+ pipelineString += "## ".concat(title_1);
1328
+ if (description_1) {
1329
+ pipelineString += '\n\n';
1330
+ pipelineString += description_1;
1331
+ }
1332
+ var commands_1 = [];
1333
+ var contentLanguage = 'text';
1334
+ if (templateType === 'PROMPT_TEMPLATE') {
1335
+ var modelRequirements = template.modelRequirements;
1336
+ var _l = modelRequirements || {}, modelName = _l.modelName, modelVariant = _l.modelVariant;
1337
+ commands_1.push("EXECUTE PROMPT TEMPLATE");
1338
+ if (modelVariant) {
1339
+ commands_1.push("MODEL VARIANT ".concat(capitalize(modelVariant)));
1460
1340
  }
1461
- // Note: [๐Ÿจ]
1462
- validatePipeline(pipeline);
1463
- // TODO: [๐Ÿฆ„] DRY
1464
- // Note: [๐Ÿฆ„]
1465
- if (
1466
- // TODO: [๐Ÿฝ]
1467
- this.collection.has(pipeline.pipelineUrl) &&
1468
- pipelineJsonToString(unpreparePipeline(pipeline)) !==
1469
- pipelineJsonToString(unpreparePipeline(this.collection.get(pipeline.pipelineUrl)))) {
1470
- var existing = this.collection.get(pipeline.pipelineUrl);
1471
- throw new PipelineUrlError(spaceTrim("\n Pipeline with URL \"".concat(pipeline.pipelineUrl, "\" is already in the collection \uD83C\uDF4E\n\n Conflicting files:\n ").concat(existing.sourceFile || 'Unknown', "\n ").concat(pipeline.sourceFile || 'Unknown', "\n\n Note: You have probably forgotten to run \"ptbk make\" to update the collection\n Note: Pipelines with the same URL are not allowed\n Only exepction is when the pipelines are identical\n\n ")));
1341
+ if (modelName) {
1342
+ commands_1.push("MODEL NAME `".concat(modelName, "`"));
1472
1343
  }
1473
- // Note: [๐Ÿง ] Overwrite existing pipeline with the same URL
1474
- this.collection.set(pipeline.pipelineUrl, pipeline);
1475
1344
  }
1476
- }
1477
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
1478
- finally {
1479
- try {
1480
- if (pipelines_1_1 && !pipelines_1_1.done && (_a = pipelines_1.return)) _a.call(pipelines_1);
1345
+ else if (templateType === 'SIMPLE_TEMPLATE') {
1346
+ commands_1.push("SIMPLE TEMPLATE");
1347
+ // Note: Nothing special here
1481
1348
  }
1482
- finally { if (e_1) throw e_1.error; }
1483
- }
1484
- }
1485
- /**
1486
- * Gets all pipelines in the collection
1487
- */
1488
- SimplePipelineCollection.prototype.listPipelines = function () {
1489
- return Array.from(this.collection.keys());
1490
- };
1491
- /**
1492
- * Gets pipeline by its URL
1493
- *
1494
- * Note: This is not a direct fetching from the URL, but a lookup in the collection
1495
- */
1496
- SimplePipelineCollection.prototype.getPipelineByUrl = function (url) {
1497
- var _this = this;
1498
- var pipeline = this.collection.get(url);
1499
- if (!pipeline) {
1500
- if (this.listPipelines().length === 0) {
1501
- throw new NotFoundError(spaceTrim("\n Pipeline with url \"".concat(url, "\" not found\n\n No pipelines available\n ")));
1349
+ else if (templateType === 'SCRIPT_TEMPLATE') {
1350
+ commands_1.push("SCRIPT TEMPLATE");
1351
+ if (template.contentLanguage) {
1352
+ contentLanguage = template.contentLanguage;
1353
+ }
1354
+ else {
1355
+ contentLanguage = '';
1356
+ }
1502
1357
  }
1503
- throw new NotFoundError(spaceTrim(function (block) { return "\n Pipeline with url \"".concat(url, "\" not found\n\n Available pipelines:\n ").concat(block(_this.listPipelines()
1504
- .map(function (pipelineUrl) { return "- ".concat(pipelineUrl); })
1505
- .join('\n')), "\n\n "); }));
1358
+ else if (templateType === 'DIALOG_TEMPLATE') {
1359
+ commands_1.push("DIALOG TEMPLATE");
1360
+ // Note: Nothing special here
1361
+ } // <- }else if([๐Ÿ…ฑ]
1362
+ if (jokers) {
1363
+ try {
1364
+ for (var jokers_1 = (e_4 = void 0, __values(jokers)), jokers_1_1 = jokers_1.next(); !jokers_1_1.done; jokers_1_1 = jokers_1.next()) {
1365
+ var joker = jokers_1_1.value;
1366
+ commands_1.push("JOKER {".concat(joker, "}"));
1367
+ }
1368
+ }
1369
+ catch (e_4_1) { e_4 = { error: e_4_1 }; }
1370
+ finally {
1371
+ try {
1372
+ if (jokers_1_1 && !jokers_1_1.done && (_d = jokers_1.return)) _d.call(jokers_1);
1373
+ }
1374
+ finally { if (e_4) throw e_4.error; }
1375
+ }
1376
+ } /* not else */
1377
+ if (postprocessing) {
1378
+ try {
1379
+ for (var postprocessing_1 = (e_5 = void 0, __values(postprocessing)), postprocessing_1_1 = postprocessing_1.next(); !postprocessing_1_1.done; postprocessing_1_1 = postprocessing_1.next()) {
1380
+ var postprocessingFunctionName = postprocessing_1_1.value;
1381
+ commands_1.push("POSTPROCESSING `".concat(postprocessingFunctionName, "`"));
1382
+ }
1383
+ }
1384
+ catch (e_5_1) { e_5 = { error: e_5_1 }; }
1385
+ finally {
1386
+ try {
1387
+ if (postprocessing_1_1 && !postprocessing_1_1.done && (_e = postprocessing_1.return)) _e.call(postprocessing_1);
1388
+ }
1389
+ finally { if (e_5) throw e_5.error; }
1390
+ }
1391
+ } /* not else */
1392
+ if (expectations) {
1393
+ try {
1394
+ for (var _m = (e_6 = void 0, __values(Object.entries(expectations))), _o = _m.next(); !_o.done; _o = _m.next()) {
1395
+ var _p = __read(_o.value, 2), unit = _p[0], _q = _p[1], min = _q.min, max = _q.max;
1396
+ if (min === max) {
1397
+ commands_1.push("EXPECT EXACTLY ".concat(min, " ").concat(capitalize(unit + (min > 1 ? 's' : ''))));
1398
+ }
1399
+ else {
1400
+ if (min !== undefined) {
1401
+ commands_1.push("EXPECT MIN ".concat(min, " ").concat(capitalize(unit + (min > 1 ? 's' : ''))));
1402
+ } /* not else */
1403
+ if (max !== undefined) {
1404
+ commands_1.push("EXPECT MAX ".concat(max, " ").concat(capitalize(unit + (max > 1 ? 's' : ''))));
1405
+ }
1406
+ }
1407
+ }
1408
+ }
1409
+ catch (e_6_1) { e_6 = { error: e_6_1 }; }
1410
+ finally {
1411
+ try {
1412
+ if (_o && !_o.done && (_f = _m.return)) _f.call(_m);
1413
+ }
1414
+ finally { if (e_6) throw e_6.error; }
1415
+ }
1416
+ } /* not else */
1417
+ if (format) {
1418
+ if (format === 'JSON') {
1419
+ // TODO: @deprecated remove
1420
+ commands_1.push("FORMAT JSON");
1421
+ }
1422
+ } /* not else */
1423
+ pipelineString += '\n\n';
1424
+ pipelineString += commands_1.map(function (command) { return "- ".concat(command); }).join('\n');
1425
+ pipelineString += '\n\n';
1426
+ pipelineString += '```' + contentLanguage;
1427
+ pipelineString += '\n';
1428
+ pipelineString += spaceTrim$1(content);
1429
+ // <- TODO: [main] !!! Escape
1430
+ // <- TODO: [๐Ÿง ] Some clear strategy how to spaceTrim the blocks
1431
+ pipelineString += '\n';
1432
+ pipelineString += '```';
1433
+ pipelineString += '\n\n';
1434
+ pipelineString += "`-> {".concat(resultingParameterName, "}`"); // <- TODO: [main] !!! If the parameter here has description, add it and use templateParameterJsonToString
1435
+ }
1436
+ }
1437
+ catch (e_3_1) { e_3 = { error: e_3_1 }; }
1438
+ finally {
1439
+ try {
1440
+ if (templates_1_1 && !templates_1_1.done && (_c = templates_1.return)) _c.call(templates_1);
1506
1441
  }
1507
- return pipeline;
1508
- };
1509
- /**
1510
- * Checks whether given prompt was defined in any pipeline in the collection
1511
- */
1512
- SimplePipelineCollection.prototype.isResponsibleForPrompt = function (prompt) {
1513
- return true;
1514
- };
1515
- return SimplePipelineCollection;
1516
- }());
1517
-
1442
+ finally { if (e_3) throw e_3.error; }
1443
+ }
1444
+ return pipelineString;
1445
+ }
1518
1446
  /**
1519
- * Creates PipelineCollection from array of PipelineJson or PipelineString
1520
- *
1521
- * Note: Functions `collectionToJson` and `createCollectionFromJson` are complementary
1522
- * Note: Syntax, parsing, and logic consistency checks are performed on all sources during build
1523
- *
1524
- * @param promptbookSources
1525
- * @returns PipelineCollection
1526
- * @public exported from `@promptbook/core`
1447
+ * @private internal utility of `pipelineJsonToString`
1527
1448
  */
1528
- function createCollectionFromJson() {
1529
- var promptbooks = [];
1530
- for (var _i = 0; _i < arguments.length; _i++) {
1531
- promptbooks[_i] = arguments[_i];
1449
+ function templateParameterJsonToString(templateParameterJson) {
1450
+ var name = templateParameterJson.name, description = templateParameterJson.description;
1451
+ var parameterString = "{".concat(name, "}");
1452
+ if (description) {
1453
+ parameterString = "".concat(parameterString, " ").concat(description);
1532
1454
  }
1533
- return new (SimplePipelineCollection.bind.apply(SimplePipelineCollection, __spreadArray([void 0], __read(promptbooks), false)))();
1455
+ return parameterString;
1534
1456
  }
1535
-
1536
- var defaultDiacriticsRemovalMap = [
1537
- {
1538
- base: 'A',
1539
- 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',
1540
- },
1541
- { base: 'AA', letters: '\uA732' },
1542
- { base: 'AE', letters: '\u00C6\u01FC\u01E2' },
1543
- { base: 'AO', letters: '\uA734' },
1544
- { base: 'AU', letters: '\uA736' },
1545
- { base: 'AV', letters: '\uA738\uA73A' },
1546
- { base: 'AY', letters: '\uA73C' },
1547
- {
1548
- base: 'B',
1549
- letters: '\u0042\u24B7\uFF22\u1E02\u1E04\u1E06\u0243\u0182\u0181',
1550
- },
1551
- {
1552
- base: 'C',
1553
- letters: '\u0043\u24B8\uFF23\u0106\u0108\u010A\u010C\u00C7\u1E08\u0187\u023B\uA73E',
1554
- },
1555
- {
1556
- base: 'D',
1557
- letters: '\u0044\u24B9\uFF24\u1E0A\u010E\u1E0C\u1E10\u1E12\u1E0E\u0110\u018B\u018A\u0189\uA779\u00D0',
1558
- },
1559
- { base: 'DZ', letters: '\u01F1\u01C4' },
1560
- { base: 'Dz', letters: '\u01F2\u01C5' },
1561
- {
1562
- base: 'E',
1563
- 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',
1564
- },
1565
- { base: 'F', letters: '\u0046\u24BB\uFF26\u1E1E\u0191\uA77B' },
1566
- {
1567
- base: 'G',
1568
- letters: '\u0047\u24BC\uFF27\u01F4\u011C\u1E20\u011E\u0120\u01E6\u0122\u01E4\u0193\uA7A0\uA77D\uA77E',
1569
- },
1570
- {
1571
- base: 'H',
1572
- letters: '\u0048\u24BD\uFF28\u0124\u1E22\u1E26\u021E\u1E24\u1E28\u1E2A\u0126\u2C67\u2C75\uA78D',
1573
- },
1574
- {
1575
- base: 'I',
1576
- letters: '\u0049\u24BE\uFF29\u00CC\u00CD\u00CE\u0128\u012A\u012C\u0130\u00CF\u1E2E\u1EC8\u01CF\u0208\u020A\u1ECA\u012E\u1E2C\u0197',
1577
- },
1578
- { base: 'J', letters: '\u004A\u24BF\uFF2A\u0134\u0248' },
1579
- {
1580
- base: 'K',
1581
- letters: '\u004B\u24C0\uFF2B\u1E30\u01E8\u1E32\u0136\u1E34\u0198\u2C69\uA740\uA742\uA744\uA7A2',
1582
- },
1583
- {
1584
- base: 'L',
1585
- letters: '\u004C\u24C1\uFF2C\u013F\u0139\u013D\u1E36\u1E38\u013B\u1E3C\u1E3A\u0141\u023D\u2C62\u2C60\uA748\uA746\uA780',
1586
- },
1587
- { base: 'LJ', letters: '\u01C7' },
1588
- { base: 'Lj', letters: '\u01C8' },
1589
- { base: 'M', letters: '\u004D\u24C2\uFF2D\u1E3E\u1E40\u1E42\u2C6E\u019C' },
1590
- {
1591
- base: 'N',
1592
- letters: '\u004E\u24C3\uFF2E\u01F8\u0143\u00D1\u1E44\u0147\u1E46\u0145\u1E4A\u1E48\u0220\u019D\uA790\uA7A4',
1593
- },
1594
- { base: 'NJ', letters: '\u01CA' },
1595
- { base: 'Nj', letters: '\u01CB' },
1596
- {
1597
- base: 'O',
1598
- 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',
1599
- },
1600
- { base: 'OI', letters: '\u01A2' },
1601
- { base: 'OO', letters: '\uA74E' },
1602
- { base: 'OU', letters: '\u0222' },
1603
- { base: 'OE', letters: '\u008C\u0152' },
1604
- { base: 'oe', letters: '\u009C\u0153' },
1605
- {
1606
- base: 'P',
1607
- letters: '\u0050\u24C5\uFF30\u1E54\u1E56\u01A4\u2C63\uA750\uA752\uA754',
1608
- },
1609
- { base: 'Q', letters: '\u0051\u24C6\uFF31\uA756\uA758\u024A' },
1610
- {
1611
- base: 'R',
1612
- letters: '\u0052\u24C7\uFF32\u0154\u1E58\u0158\u0210\u0212\u1E5A\u1E5C\u0156\u1E5E\u024C\u2C64\uA75A\uA7A6\uA782',
1613
- },
1614
- {
1615
- base: 'S',
1616
- letters: '\u0053\u24C8\uFF33\u1E9E\u015A\u1E64\u015C\u1E60\u0160\u1E66\u1E62\u1E68\u0218\u015E\u2C7E\uA7A8\uA784',
1617
- },
1618
- {
1619
- base: 'T',
1620
- letters: '\u0054\u24C9\uFF34\u1E6A\u0164\u1E6C\u021A\u0162\u1E70\u1E6E\u0166\u01AC\u01AE\u023E\uA786',
1621
- },
1622
- { base: 'TZ', letters: '\uA728' },
1623
- {
1624
- base: 'U',
1625
- 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',
1626
- },
1627
- { base: 'V', letters: '\u0056\u24CB\uFF36\u1E7C\u1E7E\u01B2\uA75E\u0245' },
1628
- { base: 'VY', letters: '\uA760' },
1629
- {
1630
- base: 'W',
1631
- letters: '\u0057\u24CC\uFF37\u1E80\u1E82\u0174\u1E86\u1E84\u1E88\u2C72',
1632
- },
1633
- { base: 'X', letters: '\u0058\u24CD\uFF38\u1E8A\u1E8C' },
1634
- {
1635
- base: 'Y',
1636
- letters: '\u0059\u24CE\uFF39\u1EF2\u00DD\u0176\u1EF8\u0232\u1E8E\u0178\u1EF6\u1EF4\u01B3\u024E\u1EFE',
1637
- },
1638
- {
1639
- base: 'Z',
1640
- letters: '\u005A\u24CF\uFF3A\u0179\u1E90\u017B\u017D\u1E92\u1E94\u01B5\u0224\u2C7F\u2C6B\uA762',
1641
- },
1642
- {
1643
- base: 'a',
1644
- 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',
1645
- },
1646
- { base: 'aa', letters: '\uA733' },
1647
- { base: 'ae', letters: '\u00E6\u01FD\u01E3' },
1648
- { base: 'ao', letters: '\uA735' },
1649
- { base: 'au', letters: '\uA737' },
1650
- { base: 'av', letters: '\uA739\uA73B' },
1651
- { base: 'ay', letters: '\uA73D' },
1652
- {
1653
- base: 'b',
1654
- letters: '\u0062\u24D1\uFF42\u1E03\u1E05\u1E07\u0180\u0183\u0253',
1655
- },
1656
- {
1657
- base: 'c',
1658
- letters: '\u0063\u24D2\uFF43\u0107\u0109\u010B\u010D\u00E7\u1E09\u0188\u023C\uA73F\u2184',
1659
- },
1660
- {
1661
- base: 'd',
1662
- letters: '\u0064\u24D3\uFF44\u1E0B\u010F\u1E0D\u1E11\u1E13\u1E0F\u0111\u018C\u0256\u0257\uA77A',
1663
- },
1664
- { base: 'dz', letters: '\u01F3\u01C6' },
1665
- {
1666
- base: 'e',
1667
- 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',
1668
- },
1669
- { base: 'f', letters: '\u0066\u24D5\uFF46\u1E1F\u0192\uA77C' },
1670
- {
1671
- base: 'g',
1672
- letters: '\u0067\u24D6\uFF47\u01F5\u011D\u1E21\u011F\u0121\u01E7\u0123\u01E5\u0260\uA7A1\u1D79\uA77F',
1673
- },
1674
- {
1675
- base: 'h',
1676
- letters: '\u0068\u24D7\uFF48\u0125\u1E23\u1E27\u021F\u1E25\u1E29\u1E2B\u1E96\u0127\u2C68\u2C76\u0265',
1677
- },
1678
- { base: 'hv', letters: '\u0195' },
1679
- {
1680
- base: 'i',
1681
- letters: '\u0069\u24D8\uFF49\u00EC\u00ED\u00EE\u0129\u012B\u012D\u00EF\u1E2F\u1EC9\u01D0\u0209\u020B\u1ECB\u012F\u1E2D\u0268\u0131',
1682
- },
1683
- { base: 'j', letters: '\u006A\u24D9\uFF4A\u0135\u01F0\u0249' },
1684
- {
1685
- base: 'k',
1686
- letters: '\u006B\u24DA\uFF4B\u1E31\u01E9\u1E33\u0137\u1E35\u0199\u2C6A\uA741\uA743\uA745\uA7A3',
1687
- },
1688
- {
1689
- base: 'l',
1690
- letters: '\u006C\u24DB\uFF4C\u0140\u013A\u013E\u1E37\u1E39\u013C\u1E3D\u1E3B\u017F\u0142\u019A\u026B\u2C61\uA749\uA781\uA747',
1691
- },
1692
- { base: 'lj', letters: '\u01C9' },
1693
- { base: 'm', letters: '\u006D\u24DC\uFF4D\u1E3F\u1E41\u1E43\u0271\u026F' },
1694
- {
1695
- base: 'n',
1696
- letters: '\u006E\u24DD\uFF4E\u01F9\u0144\u00F1\u1E45\u0148\u1E47\u0146\u1E4B\u1E49\u019E\u0272\u0149\uA791\uA7A5',
1697
- },
1698
- { base: 'nj', letters: '\u01CC' },
1699
- {
1700
- base: 'o',
1701
- 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',
1702
- },
1703
- { base: 'oi', letters: '\u01A3' },
1704
- { base: 'ou', letters: '\u0223' },
1705
- { base: 'oo', letters: '\uA74F' },
1706
- {
1707
- base: 'p',
1708
- letters: '\u0070\u24DF\uFF50\u1E55\u1E57\u01A5\u1D7D\uA751\uA753\uA755',
1709
- },
1710
- { base: 'q', letters: '\u0071\u24E0\uFF51\u024B\uA757\uA759' },
1711
- {
1712
- base: 'r',
1713
- letters: '\u0072\u24E1\uFF52\u0155\u1E59\u0159\u0211\u0213\u1E5B\u1E5D\u0157\u1E5F\u024D\u027D\uA75B\uA7A7\uA783',
1714
- },
1715
- {
1716
- base: 's',
1717
- letters: '\u0073\u24E2\uFF53\u00DF\u015B\u1E65\u015D\u1E61\u0161\u1E67\u1E63\u1E69\u0219\u015F\u023F\uA7A9\uA785\u1E9B',
1718
- },
1719
- {
1720
- base: 't',
1721
- letters: '\u0074\u24E3\uFF54\u1E6B\u1E97\u0165\u1E6D\u021B\u0163\u1E71\u1E6F\u0167\u01AD\u0288\u2C66\uA787',
1722
- },
1723
- { base: 'tz', letters: '\uA729' },
1724
- {
1725
- base: 'u',
1726
- 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',
1727
- },
1728
- { base: 'v', letters: '\u0076\u24E5\uFF56\u1E7D\u1E7F\u028B\uA75F\u028C' },
1729
- { base: 'vy', letters: '\uA761' },
1730
- {
1731
- base: 'w',
1732
- letters: '\u0077\u24E6\uFF57\u1E81\u1E83\u0175\u1E87\u1E85\u1E98\u1E89\u2C73',
1733
- },
1734
- { base: 'x', letters: '\u0078\u24E7\uFF58\u1E8B\u1E8D' },
1735
- {
1736
- base: 'y',
1737
- letters: '\u0079\u24E8\uFF59\u1EF3\u00FD\u0177\u1EF9\u0233\u1E8F\u00FF\u1EF7\u1E99\u1EF5\u01B4\u024F\u1EFF',
1738
- },
1739
- {
1740
- base: 'z',
1741
- letters: '\u007A\u24E9\uFF5A\u017A\u1E91\u017C\u017E\u1E93\u1E95\u01B6\u0225\u0240\u2C6C\uA763',
1742
- },
1743
- ];
1744
1457
  /**
1745
- * Map of letters from diacritic variant to diacritless variant
1746
- * Contains lowercase and uppercase separatelly
1458
+ * TODO: [๐Ÿ›‹] Implement new features and commands into `pipelineJsonToString` + `templateParameterJsonToString` , use `stringifyCommand`
1459
+ * TODO: [๐Ÿง ] Is there a way to auto-detect missing features in pipelineJsonToString
1460
+ * TODO: [๐Ÿ›] Maybe make some markdown builder
1461
+ * TODO: [๐Ÿ›] Escape all
1462
+ * TODO: [๐Ÿง ] Should be in generated .ptbk.md file GENERATOR_WARNING
1463
+ */
1464
+
1465
+ /**
1466
+ * This error indicates that the promptbook in a markdown format cannot be parsed into a valid promptbook object
1747
1467
  *
1748
- * > "รก" => "a"
1749
- * > "ฤ›" => "e"
1750
- * > "ฤ‚" => "A"
1751
- * > ...
1468
+ * @public exported from `@promptbook/core`
1469
+ */
1470
+ var ParseError = /** @class */ (function (_super) {
1471
+ __extends(ParseError, _super);
1472
+ function ParseError(message) {
1473
+ var _this = _super.call(this, message) || this;
1474
+ _this.name = 'ParseError';
1475
+ Object.setPrototypeOf(_this, ParseError.prototype);
1476
+ return _this;
1477
+ }
1478
+ return ParseError;
1479
+ }(Error));
1480
+ /**
1481
+ * TODO: Maybe split `ParseError` and `ApplyError`
1482
+ */
1483
+
1484
+ /**
1485
+ * This error indicates that the promptbook object has valid syntax (=can be parsed) but contains logical errors (like circular dependencies)
1486
+ *
1487
+ * @public exported from `@promptbook/core`
1488
+ */
1489
+ var PipelineLogicError = /** @class */ (function (_super) {
1490
+ __extends(PipelineLogicError, _super);
1491
+ function PipelineLogicError(message) {
1492
+ var _this = _super.call(this, message) || this;
1493
+ _this.name = 'PipelineLogicError';
1494
+ Object.setPrototypeOf(_this, PipelineLogicError.prototype);
1495
+ return _this;
1496
+ }
1497
+ return PipelineLogicError;
1498
+ }(Error));
1499
+
1500
+ /**
1501
+ * Tests if given string is valid semantic version
1502
+ *
1503
+ * Note: There are two simmilar functions:
1504
+ * - `isValidSemanticVersion` which tests any semantic version
1505
+ * - `isValidPromptbookVersion` *(this one)* which tests just Promptbook versions
1752
1506
  *
1753
1507
  * @public exported from `@promptbook/utils`
1754
1508
  */
1755
- var DIACRITIC_VARIANTS_LETTERS = {};
1756
- // tslint:disable-next-line: prefer-for-of
1757
- for (var i = 0; i < defaultDiacriticsRemovalMap.length; i++) {
1758
- var letters = defaultDiacriticsRemovalMap[i].letters;
1759
- // tslint:disable-next-line: prefer-for-of
1760
- for (var j = 0; j < letters.length; j++) {
1761
- DIACRITIC_VARIANTS_LETTERS[letters[j]] = defaultDiacriticsRemovalMap[i].base;
1509
+ function isValidSemanticVersion(version) {
1510
+ if (typeof version !== 'string') {
1511
+ return false;
1512
+ }
1513
+ if (version.startsWith('0.0.0')) {
1514
+ return false;
1515
+ }
1516
+ return /^\d+\.\d+\.\d+(-\d+)?$/i.test(version);
1517
+ }
1518
+
1519
+ /**
1520
+ * Tests if given string is valid promptbook version
1521
+ * It looks into list of known promptbook versions.
1522
+ *
1523
+ * @see https://www.npmjs.com/package/promptbook?activeTab=versions
1524
+ * 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.
1525
+ * Note: There are two simmilar functions:
1526
+ * - `isValidSemanticVersion` which tests any semantic version
1527
+ * - `isValidPromptbookVersion` *(this one)* which tests just Promptbook versions
1528
+ *
1529
+ * @public exported from `@promptbook/utils`
1530
+ */
1531
+ function isValidPromptbookVersion(version) {
1532
+ if (!isValidSemanticVersion(version)) {
1533
+ return false;
1534
+ }
1535
+ if ( /* version === '1.0.0' || */version === '2.0.0' || version === '3.0.0') {
1536
+ return false;
1537
+ }
1538
+ // <- TODO: [main] !!! Check isValidPromptbookVersion against PROMPTBOOK_VERSIONS
1539
+ return true;
1540
+ }
1541
+
1542
+ /**
1543
+ * Checks if an URL is reserved for private networks or localhost.
1544
+ *
1545
+ * Note: There are two simmilar functions:
1546
+ * - `isUrlOnPrivateNetwork` which tests full URL
1547
+ * - `isHostnameOnPrivateNetwork` *(this one)* which tests just hostname
1548
+ *
1549
+ * @public exported from `@promptbook/utils`
1550
+ */
1551
+ function isHostnameOnPrivateNetwork(hostname) {
1552
+ if (hostname === 'example.com' ||
1553
+ hostname === 'localhost' ||
1554
+ hostname.endsWith('.localhost') ||
1555
+ hostname.endsWith('.local') ||
1556
+ hostname.endsWith('.test') ||
1557
+ hostname === '127.0.0.1' ||
1558
+ hostname === '::1') {
1559
+ return true;
1560
+ }
1561
+ if (hostname.includes(':')) {
1562
+ // IPv6
1563
+ var ipParts = hostname.split(':');
1564
+ return ipParts[0] === 'fc00' || ipParts[0] === 'fd00' || ipParts[0] === 'fe80';
1565
+ }
1566
+ else {
1567
+ // IPv4
1568
+ var ipParts = hostname.split('.').map(function (part) { return Number.parseInt(part, 10); });
1569
+ return (ipParts[0] === 10 ||
1570
+ (ipParts[0] === 172 && ipParts[1] >= 16 && ipParts[1] <= 31) ||
1571
+ (ipParts[0] === 192 && ipParts[1] === 168));
1572
+ }
1573
+ }
1574
+
1575
+ /**
1576
+ * Checks if an IP address or hostname is reserved for private networks or localhost.
1577
+ *
1578
+ * Note: There are two simmilar functions:
1579
+ * - `isUrlOnPrivateNetwork` *(this one)* which tests full URL
1580
+ * - `isHostnameOnPrivateNetwork` which tests just hostname
1581
+ *
1582
+ * @param {string} ipAddress - The IP address to check.
1583
+ * @returns {boolean} Returns true if the IP address is reserved for private networks or localhost, otherwise false.
1584
+ * @public exported from `@promptbook/utils`
1585
+ */
1586
+ function isUrlOnPrivateNetwork(url) {
1587
+ if (typeof url === 'string') {
1588
+ url = new URL(url);
1589
+ }
1590
+ return isHostnameOnPrivateNetwork(url.hostname);
1591
+ }
1592
+
1593
+ /**
1594
+ * Tests if given string is valid pipeline URL URL.
1595
+ *
1596
+ * Note: There are two simmilar functions:
1597
+ * - `isValidUrl` which tests any URL
1598
+ * - `isValidPipelineUrl` *(this one)* which tests just pipeline URL
1599
+ *
1600
+ * @public exported from `@promptbook/utils`
1601
+ */
1602
+ function isValidPipelineUrl(url) {
1603
+ if (!isValidUrl(url)) {
1604
+ return false;
1605
+ }
1606
+ if (!url.startsWith('https://')) {
1607
+ return false;
1608
+ }
1609
+ if (!url.endsWith('.ptbk.md')) {
1610
+ return false;
1611
+ }
1612
+ if (url.includes('#')) {
1613
+ // TODO: [๐Ÿ ]
1614
+ return false;
1615
+ }
1616
+ if (isUrlOnPrivateNetwork(url)) {
1617
+ return false;
1618
+ }
1619
+ return true;
1620
+ }
1621
+ /**
1622
+ * TODO: [๐Ÿ ] Maybe more info why the URL is invalid
1623
+ */
1624
+
1625
+ /**
1626
+ * Validates PipelineJson if it is logically valid
1627
+ *
1628
+ * It checks:
1629
+ * - if it has correct parameters dependency
1630
+ *
1631
+ * It does NOT check:
1632
+ * - if it is valid json
1633
+ * - if it is meaningful
1634
+ *
1635
+ * @param pipeline valid or invalid PipelineJson
1636
+ * @returns the same pipeline if it is logically valid
1637
+ * @throws {PipelineLogicError} on logical error in the pipeline
1638
+ * @public exported from `@promptbook/core`
1639
+ */
1640
+ function validatePipeline(pipeline) {
1641
+ if (IS_PIPELINE_LOGIC_VALIDATED) {
1642
+ validatePipelineCore(pipeline);
1643
+ }
1644
+ else {
1645
+ try {
1646
+ validatePipelineCore(pipeline);
1647
+ }
1648
+ catch (error) {
1649
+ if (!(error instanceof PipelineLogicError)) {
1650
+ throw error;
1651
+ }
1652
+ console.error(spaceTrim(function (block) { return "\n Pipeline is not valid but logic errors are temporarily disabled via `IS_PIPELINE_LOGIC_VALIDATED`\n\n ".concat(block(error.message), "\n "); }));
1653
+ }
1654
+ }
1655
+ return pipeline;
1656
+ }
1657
+ /**
1658
+ * @private internal function for `validatePipeline`
1659
+ */
1660
+ function validatePipelineCore(pipeline) {
1661
+ // TODO: [๐Ÿง ] Maybe test if promptbook is a promise and make specific error case for that
1662
+ var e_1, _a, e_2, _b, e_3, _c;
1663
+ var pipelineIdentification = (function () {
1664
+ // Note: This is a ๐Ÿ˜ implementation of [๐Ÿšž]
1665
+ var _ = [];
1666
+ if (pipeline.sourceFile !== undefined) {
1667
+ _.push("File: ".concat(pipeline.sourceFile));
1668
+ }
1669
+ if (pipeline.pipelineUrl !== undefined) {
1670
+ _.push("Url: ".concat(pipeline.pipelineUrl));
1671
+ }
1672
+ return _.join('\n');
1673
+ })();
1674
+ if (pipeline.pipelineUrl !== undefined && !isValidPipelineUrl(pipeline.pipelineUrl)) {
1675
+ // <- Note: [๐Ÿšฒ]
1676
+ throw new PipelineLogicError(spaceTrim(function (block) { return "\n Invalid promptbook URL \"".concat(pipeline.pipelineUrl, "\"\n\n ").concat(block(pipelineIdentification), "\n "); }));
1677
+ }
1678
+ if (pipeline.promptbookVersion !== undefined && !isValidPromptbookVersion(pipeline.promptbookVersion)) {
1679
+ // <- Note: [๐Ÿšฒ]
1680
+ throw new PipelineLogicError(spaceTrim(function (block) { return "\n Invalid Promptbook Version \"".concat(pipeline.promptbookVersion, "\"\n\n ").concat(block(pipelineIdentification), "\n "); }));
1681
+ }
1682
+ // TODO: [๐Ÿง ] Maybe do here some propper JSON-schema / ZOD checking
1683
+ if (!Array.isArray(pipeline.parameters)) {
1684
+ // TODO: [๐Ÿง ] what is the correct error tp throw - maybe PromptbookSchemaError
1685
+ throw new ParseError(spaceTrim(function (block) { return "\n Pipeline is valid JSON but with wrong structure\n\n `PipelineJson.parameters` expected to be an array, but got ".concat(typeof pipeline.parameters, "\n\n ").concat(block(pipelineIdentification), "\n "); }));
1686
+ }
1687
+ // TODO: [๐Ÿง ] Maybe do here some propper JSON-schema / ZOD checking
1688
+ if (!Array.isArray(pipeline.templates)) {
1689
+ // TODO: [๐Ÿง ] what is the correct error tp throw - maybe PromptbookSchemaError
1690
+ throw new ParseError(spaceTrim(function (block) { return "\n Pipeline is valid JSON but with wrong structure\n\n `PipelineJson.templates` expected to be an array, but got ".concat(typeof pipeline.templates, "\n\n ").concat(block(pipelineIdentification), "\n "); }));
1691
+ }
1692
+ var _loop_1 = function (parameter) {
1693
+ if (parameter.isInput && parameter.isOutput) {
1694
+ throw new PipelineLogicError(spaceTrim(function (block) { return "\n\n Parameter {".concat(parameter.name, "} can not be both input and output\n\n ").concat(block(pipelineIdentification), "\n "); }));
1695
+ }
1696
+ // Note: Testing that parameter is either intermediate or output BUT not created and unused
1697
+ if (!parameter.isInput &&
1698
+ !parameter.isOutput &&
1699
+ !pipeline.templates.some(function (template) { return template.dependentParameterNames.includes(parameter.name); })) {
1700
+ throw new PipelineLogicError(spaceTrim(function (block) { return "\n Parameter {".concat(parameter.name, "} is created but not used\n\n You can declare {").concat(parameter.name, "} as output parameter by adding in the header:\n - OUTPUT PARAMETER `{").concat(parameter.name, "}` ").concat(parameter.description || '', "\n\n ").concat(block(pipelineIdentification), "\n\n "); }));
1701
+ }
1702
+ // Note: Testing that parameter is either input or result of some template
1703
+ if (!parameter.isInput &&
1704
+ !pipeline.templates.some(function (template) { return template.resultingParameterName === parameter.name; })) {
1705
+ throw new PipelineLogicError(spaceTrim(function (block) { return "\n Parameter {".concat(parameter.name, "} is declared but not defined\n\n You can do one of these:\n 1) Remove declaration of {").concat(parameter.name, "}\n 2) Add template that results in -> {").concat(parameter.name, "}\n\n ").concat(block(pipelineIdentification), "\n "); }));
1706
+ }
1707
+ };
1708
+ try {
1709
+ // Note: Check each parameter individually
1710
+ for (var _d = __values(pipeline.parameters), _e = _d.next(); !_e.done; _e = _d.next()) {
1711
+ var parameter = _e.value;
1712
+ _loop_1(parameter);
1713
+ }
1714
+ }
1715
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
1716
+ finally {
1717
+ try {
1718
+ if (_e && !_e.done && (_a = _d.return)) _a.call(_d);
1719
+ }
1720
+ finally { if (e_1) throw e_1.error; }
1721
+ }
1722
+ // Note: All input parameters are defined - so that they can be used as result of some template
1723
+ var definedParameters = new Set(pipeline.parameters.filter(function (_a) {
1724
+ var isInput = _a.isInput;
1725
+ return isInput;
1726
+ }).map(function (_a) {
1727
+ var name = _a.name;
1728
+ return name;
1729
+ }));
1730
+ var _loop_2 = function (template) {
1731
+ var e_4, _h, e_5, _j;
1732
+ if (definedParameters.has(template.resultingParameterName)) {
1733
+ throw new PipelineLogicError(spaceTrim(function (block) { return "\n Parameter {".concat(template.resultingParameterName, "} is defined multiple times\n\n ").concat(block(pipelineIdentification), "\n "); }));
1734
+ }
1735
+ if (RESERVED_PARAMETER_NAMES.includes(template.resultingParameterName)) {
1736
+ throw new PipelineLogicError(spaceTrim(function (block) { return "\n Parameter name {".concat(template.resultingParameterName, "} is reserved, please use different name\n\n ").concat(block(pipelineIdentification), "\n "); }));
1737
+ }
1738
+ definedParameters.add(template.resultingParameterName);
1739
+ if (template.jokerParameterNames && template.jokerParameterNames.length > 0) {
1740
+ if (!template.format &&
1741
+ !template.expectations /* <- TODO: Require at least 1 -> min <- expectation to use jokers */) {
1742
+ throw new PipelineLogicError(spaceTrim(function (block) { return "\n Joker parameters are used for {".concat(template.resultingParameterName, "} but no expectations are defined\n\n ").concat(block(pipelineIdentification), "\n "); }));
1743
+ }
1744
+ var _loop_4 = function (joker) {
1745
+ if (!template.dependentParameterNames.includes(joker)) {
1746
+ throw new PipelineLogicError(spaceTrim(function (block) { return "\n Parameter {".concat(joker, "} is used for {").concat(template.resultingParameterName, "} as joker but not in `dependentParameterNames`\n\n ").concat(block(pipelineIdentification), "\n "); }));
1747
+ }
1748
+ };
1749
+ try {
1750
+ for (var _k = (e_4 = void 0, __values(template.jokerParameterNames)), _l = _k.next(); !_l.done; _l = _k.next()) {
1751
+ var joker = _l.value;
1752
+ _loop_4(joker);
1753
+ }
1754
+ }
1755
+ catch (e_4_1) { e_4 = { error: e_4_1 }; }
1756
+ finally {
1757
+ try {
1758
+ if (_l && !_l.done && (_h = _k.return)) _h.call(_k);
1759
+ }
1760
+ finally { if (e_4) throw e_4.error; }
1761
+ }
1762
+ }
1763
+ if (template.expectations) {
1764
+ var _loop_5 = function (unit, min, max) {
1765
+ if (min !== undefined && max !== undefined && min > max) {
1766
+ throw new PipelineLogicError(spaceTrim(function (block) { return "\n Min expectation (=".concat(min, ") of ").concat(unit, " is higher than max expectation (=").concat(max, ")\n\n ").concat(block(pipelineIdentification), "\n "); }));
1767
+ }
1768
+ if (min !== undefined && min < 0) {
1769
+ throw new PipelineLogicError(spaceTrim(function (block) { return "\n Min expectation of ".concat(unit, " must be zero or positive\n\n ").concat(block(pipelineIdentification), "\n "); }));
1770
+ }
1771
+ if (max !== undefined && max <= 0) {
1772
+ throw new PipelineLogicError(spaceTrim(function (block) { return "\n Max expectation of ".concat(unit, " must be positive\n\n ").concat(block(pipelineIdentification), "\n "); }));
1773
+ }
1774
+ };
1775
+ try {
1776
+ for (var _m = (e_5 = void 0, __values(Object.entries(template.expectations))), _o = _m.next(); !_o.done; _o = _m.next()) {
1777
+ var _p = __read(_o.value, 2), unit = _p[0], _q = _p[1], min = _q.min, max = _q.max;
1778
+ _loop_5(unit, min, max);
1779
+ }
1780
+ }
1781
+ catch (e_5_1) { e_5 = { error: e_5_1 }; }
1782
+ finally {
1783
+ try {
1784
+ if (_o && !_o.done && (_j = _m.return)) _j.call(_m);
1785
+ }
1786
+ finally { if (e_5) throw e_5.error; }
1787
+ }
1788
+ }
1789
+ };
1790
+ try {
1791
+ // Note: Checking each template individually
1792
+ for (var _f = __values(pipeline.templates), _g = _f.next(); !_g.done; _g = _f.next()) {
1793
+ var template = _g.value;
1794
+ _loop_2(template);
1795
+ }
1796
+ }
1797
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
1798
+ finally {
1799
+ try {
1800
+ if (_g && !_g.done && (_b = _f.return)) _b.call(_f);
1801
+ }
1802
+ finally { if (e_2) throw e_2.error; }
1803
+ }
1804
+ // Note: Detect circular dependencies
1805
+ var resovedParameters = pipeline.parameters
1806
+ .filter(function (_a) {
1807
+ var isInput = _a.isInput;
1808
+ return isInput;
1809
+ })
1810
+ .map(function (_a) {
1811
+ var name = _a.name;
1812
+ return name;
1813
+ });
1814
+ try {
1815
+ // Note: All reserved parameters are resolved
1816
+ for (var RESERVED_PARAMETER_NAMES_1 = __values(RESERVED_PARAMETER_NAMES), RESERVED_PARAMETER_NAMES_1_1 = RESERVED_PARAMETER_NAMES_1.next(); !RESERVED_PARAMETER_NAMES_1_1.done; RESERVED_PARAMETER_NAMES_1_1 = RESERVED_PARAMETER_NAMES_1.next()) {
1817
+ var reservedParameterName = RESERVED_PARAMETER_NAMES_1_1.value;
1818
+ resovedParameters = __spreadArray(__spreadArray([], __read(resovedParameters), false), [reservedParameterName], false);
1819
+ }
1820
+ }
1821
+ catch (e_3_1) { e_3 = { error: e_3_1 }; }
1822
+ finally {
1823
+ try {
1824
+ if (RESERVED_PARAMETER_NAMES_1_1 && !RESERVED_PARAMETER_NAMES_1_1.done && (_c = RESERVED_PARAMETER_NAMES_1.return)) _c.call(RESERVED_PARAMETER_NAMES_1);
1825
+ }
1826
+ finally { if (e_3) throw e_3.error; }
1827
+ }
1828
+ var unresovedTemplates = __spreadArray([], __read(pipeline.templates), false);
1829
+ var loopLimit = LOOP_LIMIT;
1830
+ var _loop_3 = function () {
1831
+ if (loopLimit-- < 0) {
1832
+ // Note: Really UnexpectedError not LimitReachedError - this should not happen and be caught below
1833
+ throw new UnexpectedError(spaceTrim(function (block) { return "\n Loop limit reached during detection of circular dependencies in `validatePipeline`\n\n ".concat(block(pipelineIdentification), "\n "); }));
1834
+ }
1835
+ var currentlyResovedTemplates = unresovedTemplates.filter(function (template) {
1836
+ return template.dependentParameterNames.every(function (name) { return resovedParameters.includes(name); });
1837
+ });
1838
+ if (currentlyResovedTemplates.length === 0) {
1839
+ throw new PipelineLogicError(
1840
+ // TODO: [๐ŸŽ] DRY
1841
+ spaceTrim(function (block) { return "\n\n Can not resolve some parameters:\n Either you are using a parameter that is not defined, or there are some circular dependencies.\n\n ".concat(block(pipelineIdentification), "\n\n Can not resolve:\n ").concat(block(unresovedTemplates
1842
+ .map(function (_a) {
1843
+ var resultingParameterName = _a.resultingParameterName, dependentParameterNames = _a.dependentParameterNames;
1844
+ return "- Parameter {".concat(resultingParameterName, "} which depends on ").concat(dependentParameterNames
1845
+ .map(function (dependentParameterName) { return "{".concat(dependentParameterName, "}"); })
1846
+ .join(' and '));
1847
+ })
1848
+ .join('\n')), "\n\n Resolved:\n ").concat(block(resovedParameters.map(function (name) { return "- Parameter {".concat(name, "}"); }).join('\n')), "\n\n\n "); }));
1849
+ }
1850
+ resovedParameters = __spreadArray(__spreadArray([], __read(resovedParameters), false), __read(currentlyResovedTemplates.map(function (_a) {
1851
+ var resultingParameterName = _a.resultingParameterName;
1852
+ return resultingParameterName;
1853
+ })), false);
1854
+ unresovedTemplates = unresovedTemplates.filter(function (template) { return !currentlyResovedTemplates.includes(template); });
1855
+ };
1856
+ while (unresovedTemplates.length > 0) {
1857
+ _loop_3();
1762
1858
  }
1763
1859
  }
1764
- // <- TODO: [๐Ÿ“] Put to maker function to save execution time if not needed
1765
- /*
1766
- @see https://stackoverflow.com/questions/990904/remove-accents-diacritics-in-a-string-in-javascript
1767
- Licensed under the Apache License, Version 2.0 (the "License");
1768
- you may not use this file except in compliance with the License.
1769
- You may obtain a copy of the License at
1770
-
1771
- http://www.apache.org/licenses/LICENSE-2.0
1772
-
1773
- Unless required by applicable law or agreed to in writing, software
1774
- distributed under the License is distributed on an "AS IS" BASIS,
1775
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1776
- See the License for the specific language governing permissions and
1777
- limitations under the License.
1778
- */
1779
-
1780
1860
  /**
1781
- * @@@
1782
- *
1783
- * @param input @@@
1784
- * @returns @@@
1785
- * @public exported from `@promptbook/utils`
1861
+ * TODO: !!!!! [๐Ÿงžโ€โ™€๏ธ] Do not allow joker + foreach
1862
+ * TODO: [๐Ÿง ] Work with promptbookVersion
1863
+ * TODO: Use here some json-schema, Zod or something similar and change it to:
1864
+ * > /**
1865
+ * > * Validates PipelineJson if it is logically valid.
1866
+ * > *
1867
+ * > * It checks:
1868
+ * > * - it has a valid structure
1869
+ * > * - ...
1870
+ * > ex port function validatePipeline(promptbook: really_unknown): asserts promptbook is PipelineJson {
1786
1871
  */
1787
- function removeDiacritics(input) {
1788
- /*eslint no-control-regex: "off"*/
1789
- return input.replace(/[^\u0000-\u007E]/g, function (a) {
1790
- return DIACRITIC_VARIANTS_LETTERS[a] || a;
1791
- });
1792
- }
1793
1872
  /**
1794
- * TODO: [ะ–] Variant for cyrillic (and in general non-latin) letters
1873
+ * TODO: [๐Ÿงณ][main] !!!! Validate that all samples match expectations
1874
+ * TODO: [๐Ÿงณ][๐Ÿ][main] !!!! Validate that knowledge is valid (non-void)
1875
+ * TODO: [๐Ÿงณ][main] !!!! Validate that persona can be used only with CHAT variant
1876
+ * TODO: [๐Ÿงณ][main] !!!! Validate that parameter with reserved name not used RESERVED_PARAMETER_NAMES
1877
+ * TODO: [๐Ÿงณ][main] !!!! Validate that reserved parameter is not used as joker
1878
+ * TODO: [๐Ÿง ] Validation not only logic itself but imports around - files and websites and rerefenced pipelines exists
1879
+ * TODO: [๐Ÿ› ] Actions, instruments (and maybe knowledge) => Functions and tools
1795
1880
  */
1796
1881
 
1797
1882
  /**
1798
- * @@@
1883
+ * This error indicates that promptbook not found in the collection
1799
1884
  *
1800
- * @param text @@@
1801
- * @returns @@@
1802
- * @example 'hello-world'
1803
- * @example 'i-love-promptbook'
1804
- * @public exported from `@promptbook/utils`
1885
+ * @public exported from `@promptbook/core`
1805
1886
  */
1806
- function normalizeToKebabCase(text) {
1807
- var e_1, _a;
1808
- text = removeDiacritics(text);
1809
- var charType;
1810
- var lastCharType = 'OTHER';
1811
- var normalizedName = '';
1812
- try {
1813
- for (var text_1 = __values(text), text_1_1 = text_1.next(); !text_1_1.done; text_1_1 = text_1.next()) {
1814
- var char = text_1_1.value;
1815
- var normalizedChar = void 0;
1816
- if (/^[a-z]$/.test(char)) {
1817
- charType = 'LOWERCASE';
1818
- normalizedChar = char;
1819
- }
1820
- else if (/^[A-Z]$/.test(char)) {
1821
- charType = 'UPPERCASE';
1822
- normalizedChar = char.toLowerCase();
1823
- }
1824
- else if (/^[0-9]$/.test(char)) {
1825
- charType = 'NUMBER';
1826
- normalizedChar = char;
1827
- }
1828
- else {
1829
- charType = 'OTHER';
1830
- normalizedChar = '-';
1831
- }
1832
- if (charType !== lastCharType &&
1833
- !(lastCharType === 'UPPERCASE' && charType === 'LOWERCASE') &&
1834
- !(lastCharType === 'NUMBER') &&
1835
- !(charType === 'NUMBER')) {
1836
- normalizedName += '-';
1837
- }
1838
- normalizedName += normalizedChar;
1839
- lastCharType = charType;
1887
+ var NotFoundError = /** @class */ (function (_super) {
1888
+ __extends(NotFoundError, _super);
1889
+ function NotFoundError(message) {
1890
+ var _this = _super.call(this, message) || this;
1891
+ _this.name = 'NotFoundError';
1892
+ Object.setPrototypeOf(_this, NotFoundError.prototype);
1893
+ return _this;
1894
+ }
1895
+ return NotFoundError;
1896
+ }(Error));
1897
+
1898
+ /**
1899
+ * This error indicates errors in referencing promptbooks between each other
1900
+ *
1901
+ * @public exported from `@promptbook/core`
1902
+ */
1903
+ var PipelineUrlError = /** @class */ (function (_super) {
1904
+ __extends(PipelineUrlError, _super);
1905
+ function PipelineUrlError(message) {
1906
+ var _this = _super.call(this, message) || this;
1907
+ _this.name = 'PipelineUrlError';
1908
+ Object.setPrototypeOf(_this, PipelineUrlError.prototype);
1909
+ return _this;
1910
+ }
1911
+ return PipelineUrlError;
1912
+ }(Error));
1913
+
1914
+ /**
1915
+ * Parses the template and returns the list of all parameter names
1916
+ *
1917
+ * @param template the template with parameters in {curly} braces
1918
+ * @returns the list of parameter names
1919
+ * @public exported from `@promptbook/utils`
1920
+ */
1921
+ function extractParameterNames(template) {
1922
+ var e_1, _a;
1923
+ var matches = template.matchAll(/{\w+}/g);
1924
+ var parameterNames = new Set();
1925
+ try {
1926
+ for (var matches_1 = __values(matches), matches_1_1 = matches_1.next(); !matches_1_1.done; matches_1_1 = matches_1.next()) {
1927
+ var match = matches_1_1.value;
1928
+ var parameterName = match[0].slice(1, -1);
1929
+ parameterNames.add(parameterName);
1840
1930
  }
1841
1931
  }
1842
1932
  catch (e_1_1) { e_1 = { error: e_1_1 }; }
1843
1933
  finally {
1844
1934
  try {
1845
- if (text_1_1 && !text_1_1.done && (_a = text_1.return)) _a.call(text_1);
1935
+ if (matches_1_1 && !matches_1_1.done && (_a = matches_1.return)) _a.call(matches_1);
1846
1936
  }
1847
1937
  finally { if (e_1) throw e_1.error; }
1848
1938
  }
1849
- normalizedName = normalizedName.split(/-+/g).join('-');
1850
- normalizedName = normalizedName.split(/-?\/-?/g).join('/');
1851
- normalizedName = normalizedName.replace(/^-/, '');
1852
- normalizedName = normalizedName.replace(/-$/, '');
1853
- return normalizedName;
1939
+ return parameterNames;
1854
1940
  }
1855
1941
 
1856
1942
  /**
1857
- * Removes emojis from a string and fix whitespaces
1943
+ * Unprepare just strips the preparation data of the pipeline
1858
1944
  *
1859
- * @param text with emojis
1860
- * @returns text without emojis
1861
- * @public exported from `@promptbook/utils`
1945
+ * @public exported from `@promptbook/core`
1862
1946
  */
1863
- function removeEmojis(text) {
1864
- // Replace emojis (and also ZWJ sequence) with hyphens
1865
- text = text.replace(/(\p{Extended_Pictographic})\p{Modifier_Symbol}/gu, '$1');
1866
- text = text.replace(/(\p{Extended_Pictographic})[\u{FE00}-\u{FE0F}]/gu, '$1');
1867
- text = text.replace(/(\p{Extended_Pictographic})(\u{200D}\p{Extended_Pictographic})*/gu, '$1');
1868
- text = text.replace(/\p{Extended_Pictographic}/gu, '');
1869
- return text;
1947
+ function unpreparePipeline(pipeline) {
1948
+ var personas = pipeline.personas, knowledgeSources = pipeline.knowledgeSources, templates = pipeline.templates;
1949
+ personas = personas.map(function (persona) { return (__assign(__assign({}, persona), { modelRequirements: undefined, preparationIds: undefined })); });
1950
+ knowledgeSources = knowledgeSources.map(function (knowledgeSource) { return (__assign(__assign({}, knowledgeSource), { preparationIds: undefined })); });
1951
+ templates = templates.map(function (template) {
1952
+ var dependentParameterNames = template.dependentParameterNames;
1953
+ var parameterNames = extractParameterNames(template.preparedContent || '');
1954
+ dependentParameterNames = dependentParameterNames.filter(function (dependentParameterName) { return !parameterNames.has(dependentParameterName); });
1955
+ var templateUnprepared = __assign(__assign({}, template), { dependentParameterNames: dependentParameterNames });
1956
+ delete templateUnprepared.preparedContent;
1957
+ return templateUnprepared;
1958
+ });
1959
+ return $asDeeplyFrozenSerializableJson('Unprepared PipelineJson', __assign(__assign({}, pipeline), { templates: templates, knowledgeSources: knowledgeSources, knowledgePieces: [], personas: personas, preparations: [] }));
1870
1960
  }
1961
+ /**
1962
+ * TODO: [๐Ÿงฟ] Maybe do same process with same granularity and subfinctions as `preparePipeline`
1963
+ * TODO: Write tests for `preparePipeline`
1964
+ * TODO: [๐Ÿ™] Make some standard order of json properties
1965
+ */
1871
1966
 
1872
1967
  /**
1873
- * Tests if given string is valid URL.
1968
+ * Library of pipelines that groups together pipelines for an application.
1969
+ * This implementation is a very thin wrapper around the Array / Map of pipelines.
1874
1970
  *
1875
- * Note: This does not check if the file exists only if the path is valid
1876
- * @public exported from `@promptbook/utils`
1971
+ * @private internal function of `createCollectionFromJson`, use `createCollectionFromJson` instead
1972
+ * @see https://github.com/webgptorg/pipeline#pipeline-collection
1877
1973
  */
1878
- function isValidFilePath(filename) {
1879
- if (typeof filename !== 'string') {
1880
- return false;
1881
- }
1882
- var filenameSlashes = filename.split('\\').join('/');
1883
- // Absolute Unix path: /hello.txt
1884
- if (/^(\/)/i.test(filenameSlashes)) {
1885
- return true;
1886
- }
1887
- // Absolute Windows path: /hello.txt
1888
- if (/^([A-Z]{1,2}:\/?)\//i.test(filenameSlashes)) {
1889
- return true;
1974
+ var SimplePipelineCollection = /** @class */ (function () {
1975
+ /**
1976
+ * Constructs a pipeline collection from pipelines
1977
+ *
1978
+ * @param pipelines @@@
1979
+ *
1980
+ * Note: During the construction logic of all pipelines are validated
1981
+ * Note: It is not recommended to use this constructor directly, use `createCollectionFromJson` *(or other variant)* instead
1982
+ */
1983
+ function SimplePipelineCollection() {
1984
+ var e_1, _a;
1985
+ var pipelines = [];
1986
+ for (var _i = 0; _i < arguments.length; _i++) {
1987
+ pipelines[_i] = arguments[_i];
1988
+ }
1989
+ this.collection = new Map();
1990
+ try {
1991
+ for (var pipelines_1 = __values(pipelines), pipelines_1_1 = pipelines_1.next(); !pipelines_1_1.done; pipelines_1_1 = pipelines_1.next()) {
1992
+ var pipeline = pipelines_1_1.value;
1993
+ // TODO: [๐Ÿ‘ ] DRY
1994
+ if (pipeline.pipelineUrl === undefined) {
1995
+ throw new PipelineUrlError(spaceTrim("\n Pipeline with name \"".concat(pipeline.title, "\" does not have defined URL\n\n File:\n ").concat(pipeline.sourceFile || 'Unknown', "\n\n Note: Pipelines without URLs are called anonymous pipelines\n They can be used as standalone pipelines, but they cannot be referenced by other pipelines\n And also they cannot be used in the pipeline collection\n\n ")));
1996
+ }
1997
+ // Note: [๐Ÿจ]
1998
+ validatePipeline(pipeline);
1999
+ // TODO: [๐Ÿฆ„] DRY
2000
+ // Note: [๐Ÿฆ„]
2001
+ if (
2002
+ // TODO: [๐Ÿฝ]
2003
+ this.collection.has(pipeline.pipelineUrl) &&
2004
+ pipelineJsonToString(unpreparePipeline(pipeline)) !==
2005
+ pipelineJsonToString(unpreparePipeline(this.collection.get(pipeline.pipelineUrl)))) {
2006
+ var existing = this.collection.get(pipeline.pipelineUrl);
2007
+ throw new PipelineUrlError(spaceTrim("\n Pipeline with URL \"".concat(pipeline.pipelineUrl, "\" is already in the collection \uD83C\uDF4E\n\n Conflicting files:\n ").concat(existing.sourceFile || 'Unknown', "\n ").concat(pipeline.sourceFile || 'Unknown', "\n\n Note: You have probably forgotten to run \"ptbk make\" to update the collection\n Note: Pipelines with the same URL are not allowed\n Only exepction is when the pipelines are identical\n\n ")));
2008
+ }
2009
+ // Note: [๐Ÿง ] Overwrite existing pipeline with the same URL
2010
+ this.collection.set(pipeline.pipelineUrl, pipeline);
2011
+ }
2012
+ }
2013
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
2014
+ finally {
2015
+ try {
2016
+ if (pipelines_1_1 && !pipelines_1_1.done && (_a = pipelines_1.return)) _a.call(pipelines_1);
2017
+ }
2018
+ finally { if (e_1) throw e_1.error; }
2019
+ }
1890
2020
  }
1891
- // Relative path: ./hello.txt
1892
- if (/^(\.\.?\/)+/i.test(filenameSlashes)) {
2021
+ /**
2022
+ * Gets all pipelines in the collection
2023
+ */
2024
+ SimplePipelineCollection.prototype.listPipelines = function () {
2025
+ return Array.from(this.collection.keys());
2026
+ };
2027
+ /**
2028
+ * Gets pipeline by its URL
2029
+ *
2030
+ * Note: This is not a direct fetching from the URL, but a lookup in the collection
2031
+ */
2032
+ SimplePipelineCollection.prototype.getPipelineByUrl = function (url) {
2033
+ var _this = this;
2034
+ var pipeline = this.collection.get(url);
2035
+ if (!pipeline) {
2036
+ if (this.listPipelines().length === 0) {
2037
+ throw new NotFoundError(spaceTrim("\n Pipeline with url \"".concat(url, "\" not found\n\n No pipelines available\n ")));
2038
+ }
2039
+ throw new NotFoundError(spaceTrim(function (block) { return "\n Pipeline with url \"".concat(url, "\" not found\n\n Available pipelines:\n ").concat(block(_this.listPipelines()
2040
+ .map(function (pipelineUrl) { return "- ".concat(pipelineUrl); })
2041
+ .join('\n')), "\n\n "); }));
2042
+ }
2043
+ return pipeline;
2044
+ };
2045
+ /**
2046
+ * Checks whether given prompt was defined in any pipeline in the collection
2047
+ */
2048
+ SimplePipelineCollection.prototype.isResponsibleForPrompt = function (prompt) {
1893
2049
  return true;
1894
- }
1895
- return false;
1896
- }
2050
+ };
2051
+ return SimplePipelineCollection;
2052
+ }());
1897
2053
 
1898
2054
  /**
1899
- * @@@
2055
+ * Creates PipelineCollection from array of PipelineJson or PipelineString
1900
2056
  *
1901
- * @param value @@@
1902
- * @returns @@@
1903
- * @example @@@
1904
- * @public exported from `@promptbook/utils`
2057
+ * Note: Functions `collectionToJson` and `createCollectionFromJson` are complementary
2058
+ * Note: Syntax, parsing, and logic consistency checks are performed on all sources during build
2059
+ *
2060
+ * @param promptbookSources
2061
+ * @returns PipelineCollection
2062
+ * @public exported from `@promptbook/core`
1905
2063
  */
1906
- function titleToName(value) {
1907
- if (isValidUrl(value)) {
1908
- value = value.replace(/^https?:\/\//, '');
1909
- value = value.replace(/\.html$/, '');
1910
- }
1911
- else if (isValidFilePath(value)) {
1912
- value = basename(value);
1913
- // Note: Keeping extension in the name
2064
+ function createCollectionFromJson() {
2065
+ var promptbooks = [];
2066
+ for (var _i = 0; _i < arguments.length; _i++) {
2067
+ promptbooks[_i] = arguments[_i];
1914
2068
  }
1915
- value = value.split('/').join('-');
1916
- value = removeEmojis(value);
1917
- value = normalizeToKebabCase(value);
1918
- // TODO: [๐Ÿง ] Maybe warn or add some padding to short name which are not good identifiers
1919
- return value;
2069
+ return new (SimplePipelineCollection.bind.apply(SimplePipelineCollection, __spreadArray([void 0], __read(promptbooks), false)))();
1920
2070
  }
1921
2071
 
1922
2072
  /**
@@ -1967,22 +2117,6 @@ var CollectionError = /** @class */ (function (_super) {
1967
2117
  return CollectionError;
1968
2118
  }(Error));
1969
2119
 
1970
- /**
1971
- * This error type indicates that you try to use a feature that is not available in the current environment
1972
- *
1973
- * @public exported from `@promptbook/core`
1974
- */
1975
- var EnvironmentMismatchError = /** @class */ (function (_super) {
1976
- __extends(EnvironmentMismatchError, _super);
1977
- function EnvironmentMismatchError(message) {
1978
- var _this = _super.call(this, message) || this;
1979
- _this.name = 'EnvironmentMismatchError';
1980
- Object.setPrototypeOf(_this, EnvironmentMismatchError.prototype);
1981
- return _this;
1982
- }
1983
- return EnvironmentMismatchError;
1984
- }(Error));
1985
-
1986
2120
  /**
1987
2121
  * This error occurs when some expectation is not met in the execution of the pipeline
1988
2122
  *
@@ -2822,22 +2956,6 @@ function preparePersona(personaDescription, tools, options) {
2822
2956
  * TODO: [๐Ÿข] !! Check validity of `temperature` in pipeline
2823
2957
  */
2824
2958
 
2825
- /**
2826
- * This error indicates that the promptbook can not retrieve knowledge from external sources
2827
- *
2828
- * @public exported from `@promptbook/core`
2829
- */
2830
- var KnowledgeScrapeError = /** @class */ (function (_super) {
2831
- __extends(KnowledgeScrapeError, _super);
2832
- function KnowledgeScrapeError(message) {
2833
- var _this = _super.call(this, message) || this;
2834
- _this.name = 'KnowledgeScrapeError';
2835
- Object.setPrototypeOf(_this, KnowledgeScrapeError.prototype);
2836
- return _this;
2837
- }
2838
- return KnowledgeScrapeError;
2839
- }(Error));
2840
-
2841
2959
  /**
2842
2960
  * @@@
2843
2961
  *
@@ -4183,27 +4301,6 @@ function extractJsonBlock(markdown) {
4183
4301
  * TODO: [๐Ÿข] Make this logic part of `JsonFormatDefinition` or `isValidJsonString`
4184
4302
  */
4185
4303
 
4186
- /**
4187
- * Just says that the variable is not used but should be kept
4188
- * No side effects.
4189
- *
4190
- * Note: It can be usefull for:
4191
- *
4192
- * 1) Suppressing eager optimization of unused imports
4193
- * 2) Suppressing eslint errors of unused variables in the tests
4194
- * 3) Keeping the type of the variable for type testing
4195
- *
4196
- * @param value any values
4197
- * @returns void
4198
- * @private within the repository
4199
- */
4200
- function keepUnused() {
4201
- var valuesToKeep = [];
4202
- for (var _i = 0; _i < arguments.length; _i++) {
4203
- valuesToKeep[_i] = arguments[_i];
4204
- }
4205
- }
4206
-
4207
4304
  /**
4208
4305
  * Replaces parameters in template with values from parameters object
4209
4306
  *
@@ -5728,13 +5825,26 @@ var WebsiteScraper = /** @class */ (function () {
5728
5825
  this.tools = tools;
5729
5826
  this.options = options;
5730
5827
  this.markdownScraper = new MarkdownScraper(tools, options);
5731
- // TODO: !!!!!! Remove
5828
+ this.showdownConverter = createShowdownConverter();
5829
+ /**/
5830
+ // TODO: [๐Ÿ„] !!!!!! Remove or describe why it is here
5732
5831
  TODO_USE(Readability);
5733
5832
  TODO_USE(Converter);
5734
5833
  TODO_USE(JSDOM);
5735
- TODO_USE(new JSDOM());
5736
5834
  TODO_USE(createShowdownConverter);
5737
- this.showdownConverter = createShowdownConverter();
5835
+ /**/
5836
+ /**/
5837
+ var jsdom = new JSDOM();
5838
+ var reader = new Readability(jsdom.window.document);
5839
+ keepUnused(reader);
5840
+ /**/
5841
+ /**/
5842
+ keepUnused(DEFAULT_INTERMEDIATE_FILES_STRATEGY, DEFAULT_IS_VERBOSE, DEFAULT_SCRAPE_CACHE_DIRNAME);
5843
+ keepUnused(EnvironmentMismatchError);
5844
+ keepUnused(KnowledgeScrapeError);
5845
+ keepUnused(getScraperIntermediateSource);
5846
+ keepUnused();
5847
+ /**/
5738
5848
  }
5739
5849
  Object.defineProperty(WebsiteScraper.prototype, "metadata", {
5740
5850
  /**
@@ -5753,10 +5863,55 @@ var WebsiteScraper = /** @class */ (function () {
5753
5863
  */
5754
5864
  WebsiteScraper.prototype.$convert = function (source) {
5755
5865
  return __awaiter(this, void 0, void 0, function () {
5756
- var markdown;
5757
- return __generator(this, function (_a) {
5758
- markdown = "";
5759
- return [2 /*return*/, __assign(__assign({}, source), { markdown: markdown, destroy: function () { } })];
5866
+ var _a, _b,
5867
+ // TODO: [๐Ÿง ] Maybe in node use headless browser not just JSDOM
5868
+ rootDirname, _c, cacheDirname, _d, intermediateFilesStrategy, _e, isVerbose, jsdom, _f, reader, article, html, i, cacheFilehandler, markdown;
5869
+ return __generator(this, function (_g) {
5870
+ switch (_g.label) {
5871
+ case 0:
5872
+ _a = this.options, _b = _a.rootDirname, rootDirname = _b === void 0 ? process.cwd() : _b, _c = _a.cacheDirname, cacheDirname = _c === void 0 ? DEFAULT_SCRAPE_CACHE_DIRNAME : _c, _d = _a.intermediateFilesStrategy, intermediateFilesStrategy = _d === void 0 ? DEFAULT_INTERMEDIATE_FILES_STRATEGY : _d, _e = _a.isVerbose, isVerbose = _e === void 0 ? DEFAULT_IS_VERBOSE : _e;
5873
+ // [๐Ÿ„] !!!!!!!
5874
+ keepUnused(rootDirname, cacheDirname, intermediateFilesStrategy, isVerbose);
5875
+ if (source.url === null) {
5876
+ throw new KnowledgeScrapeError('Website scraper requires URL');
5877
+ }
5878
+ if (this.tools.fs === undefined) {
5879
+ throw new EnvironmentMismatchError('Can not scrape websites without filesystem tools');
5880
+ }
5881
+ _f = JSDOM.bind;
5882
+ return [4 /*yield*/, source.asText()];
5883
+ case 1:
5884
+ jsdom = new (_f.apply(JSDOM, [void 0, _g.sent(), {
5885
+ // <- TODO: !!!!!!! Problem with build is probbably in `new JSDOM();`
5886
+ url: source.url,
5887
+ }]))();
5888
+ // [๐Ÿ„] !!!!!!!
5889
+ keepUnused(jsdom);
5890
+ reader = new Readability(jsdom.window.document);
5891
+ article = reader.parse();
5892
+ html = (article === null || article === void 0 ? void 0 : article.content) || (article === null || article === void 0 ? void 0 : article.textContent) || jsdom.window.document.body.innerHTML;
5893
+ // Note: Unwrap html such as it is convertable by `markdownConverter`
5894
+ for (i = 0; i < 2; i++) {
5895
+ html = html.replace(/<div\s*(?:id="readability-page-\d+"\s+class="page")?>(.*)<\/div>/is, '$1');
5896
+ }
5897
+ if (html.includes('<div')) {
5898
+ html = (article === null || article === void 0 ? void 0 : article.textContent) || '';
5899
+ }
5900
+ return [4 /*yield*/, getScraperIntermediateSource(source, {
5901
+ rootDirname: rootDirname,
5902
+ cacheDirname: cacheDirname,
5903
+ intermediateFilesStrategy: intermediateFilesStrategy,
5904
+ extension: 'html',
5905
+ isVerbose: isVerbose,
5906
+ })];
5907
+ case 2:
5908
+ cacheFilehandler = _g.sent();
5909
+ return [4 /*yield*/, this.tools.fs.writeFile(cacheFilehandler.filename, html, 'utf-8')];
5910
+ case 3:
5911
+ _g.sent();
5912
+ markdown = this.showdownConverter.makeMarkdown(html, jsdom.window.document);
5913
+ return [2 /*return*/, __assign(__assign({}, cacheFilehandler), { markdown: markdown })];
5914
+ }
5760
5915
  });
5761
5916
  });
5762
5917
  };