@promptbook/cli 0.86.8 → 0.86.10
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/README.md +3 -4
- package/esm/index.es.js +811 -680
- package/esm/index.es.js.map +1 -1
- package/esm/typings/src/conversion/archive/loadArchive.d.ts +16 -0
- package/esm/typings/src/conversion/archive/saveArchive.d.ts +18 -0
- package/esm/typings/src/conversion/validation/_importPipeline.d.ts +3 -10
- package/package.json +1 -1
- package/umd/index.umd.js +811 -680
- package/umd/index.umd.js.map +1 -1
- package/esm/typings/src/utils/editable/utils/stringifyPipelineJson.test.d.ts +0 -1
package/esm/index.es.js
CHANGED
|
@@ -44,7 +44,7 @@ var BOOK_LANGUAGE_VERSION = '1.0.0';
|
|
|
44
44
|
* @generated
|
|
45
45
|
* @see https://github.com/webgptorg/promptbook
|
|
46
46
|
*/
|
|
47
|
-
var PROMPTBOOK_ENGINE_VERSION = '0.86.
|
|
47
|
+
var PROMPTBOOK_ENGINE_VERSION = '0.86.10';
|
|
48
48
|
/**
|
|
49
49
|
* TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
|
|
50
50
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
@@ -3673,23 +3673,6 @@ function collectionToJson(collection) {
|
|
|
3673
3673
|
* TODO: [🧠] Maybe clear `sourceFile` or clear when exposing through API or remote server
|
|
3674
3674
|
*/
|
|
3675
3675
|
|
|
3676
|
-
var PipelineCollection = [{title:"Prepare Knowledge from Markdown",pipelineUrl:"https://promptbook.studio/promptbook/prepare-knowledge-from-markdown.book",formfactorName:"GENERIC",parameters:[{name:"knowledgeContent",description:"Markdown document content",isInput:true,isOutput:false},{name:"knowledgePieces",description:"The knowledge JSON object",isInput:false,isOutput:true}],tasks:[{taskType:"PROMPT_TASK",name:"knowledge",title:"Knowledge",content:"You are experienced data researcher, extract the important knowledge from the document.\n\n# Rules\n\n- Make pieces of information concise, clear, and easy to understand\n- One piece of information should be approximately 1 paragraph\n- Divide the paragraphs by markdown horizontal lines ---\n- Omit irrelevant information\n- Group redundant information\n- Write just extracted information, nothing else\n\n# The document\n\nTake information from this document:\n\n> {knowledgeContent}",resultingParameterName:"knowledgePieces",dependentParameterNames:["knowledgeContent"]}],personas:[],preparations:[],knowledgeSources:[],knowledgePieces:[],sources:[{type:"BOOK",path:null,content:"# Prepare Knowledge from Markdown\n\n- PIPELINE URL `https://promptbook.studio/promptbook/prepare-knowledge-from-markdown.book`\n- INPUT PARAMETER `{knowledgeContent}` Markdown document content\n- OUTPUT PARAMETER `{knowledgePieces}` The knowledge JSON object\n\n## Knowledge\n\n<!-- TODO: [🍆] -FORMAT JSON -->\n\n```markdown\nYou 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}\n```\n\n`-> {knowledgePieces}`\n"}],sourceFile:"./books/prepare-knowledge-from-markdown.book"},{title:"Prepare Keywords",pipelineUrl:"https://promptbook.studio/promptbook/prepare-knowledge-keywords.book",formfactorName:"GENERIC",parameters:[{name:"knowledgePieceContent",description:"The content",isInput:true,isOutput:false},{name:"keywords",description:"Keywords separated by comma",isInput:false,isOutput:true}],tasks:[{taskType:"PROMPT_TASK",name:"knowledge",title:"Knowledge",content:"You are experienced data researcher, detect the important keywords in the document.\n\n# Rules\n\n- Write just keywords separated by comma\n\n# The document\n\nTake information from this document:\n\n> {knowledgePieceContent}",resultingParameterName:"keywords",dependentParameterNames:["knowledgePieceContent"]}],personas:[],preparations:[],knowledgeSources:[],knowledgePieces:[],sources:[{type:"BOOK",path:null,content:"# Prepare Keywords\n\n- PIPELINE URL `https://promptbook.studio/promptbook/prepare-knowledge-keywords.book`\n- INPUT PARAMETER `{knowledgePieceContent}` The content\n- OUTPUT PARAMETER `{keywords}` Keywords separated by comma\n\n## Knowledge\n\n<!-- TODO: [🍆] -FORMAT JSON -->\n\n```markdown\nYou 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}\n```\n\n`-> {keywords}`\n"}],sourceFile:"./books/prepare-knowledge-keywords.book"},{title:"Prepare Knowledge-piece Title",pipelineUrl:"https://promptbook.studio/promptbook/prepare-knowledge-title.book",formfactorName:"GENERIC",parameters:[{name:"knowledgePieceContent",description:"The content",isInput:true,isOutput:false},{name:"title",description:"The title of the document",isInput:false,isOutput:true}],tasks:[{taskType:"PROMPT_TASK",name:"knowledge",title:"Knowledge",content:"You are experienced content creator, write best title for the document.\n\n# Rules\n\n- Write just title, nothing else\n- Write maximum 5 words for the title\n\n# The document\n\n> {knowledgePieceContent}",resultingParameterName:"title",expectations:{words:{min:1,max:8}},dependentParameterNames:["knowledgePieceContent"]}],personas:[],preparations:[],knowledgeSources:[],knowledgePieces:[],sources:[{type:"BOOK",path:null,content:"# Prepare Knowledge-piece Title\n\n- PIPELINE URL `https://promptbook.studio/promptbook/prepare-knowledge-title.book`\n- INPUT PARAMETER `{knowledgePieceContent}` The content\n- OUTPUT PARAMETER `{title}` The title of the document\n\n## Knowledge\n\n- EXPECT MIN 1 WORD\n- EXPECT MAX 8 WORDS\n\n```markdown\nYou are experienced content creator, write best title for the document.\n\n# Rules\n\n- Write just title, nothing else\n- Write maximum 5 words for the title\n\n# The document\n\n> {knowledgePieceContent}\n```\n\n`-> {title}`\n"}],sourceFile:"./books/prepare-knowledge-title.book"},{title:"Prepare Persona",pipelineUrl:"https://promptbook.studio/promptbook/prepare-persona.book",formfactorName:"GENERIC",parameters:[{name:"availableModelNames",description:"List of available model names separated by comma (,)",isInput:true,isOutput:false},{name:"personaDescription",description:"Description of the persona",isInput:true,isOutput:false},{name:"modelRequirements",description:"Specific requirements for the model",isInput:false,isOutput:true}],tasks:[{taskType:"PROMPT_TASK",name:"make-model-requirements",title:"Make modelRequirements",content:"You are experienced AI engineer, you need to create virtual assistant.\nWrite\n\n## Example\n\n```json\n{\n\"modelName\": \"gpt-4o\",\n\"systemMessage\": \"You are experienced AI engineer and helpfull assistant.\",\n\"temperature\": 0.7\n}\n```\n\n## Instructions\n\n- Your output format is JSON object\n- Write just the JSON object, no other text should be present\n- It contains the following keys:\n - `modelName`: The name of the model to use\n - `systemMessage`: The system message to provide context to the model\n - `temperature`: The sampling temperature to use\n\n### Key `modelName`\n\nPick from the following models:\n\n- {availableModelNames}\n\n### Key `systemMessage`\n\nThe system message is used to communicate instructions or provide context to the model at the beginning of a conversation. It is displayed in a different format compared to user messages, helping the model understand its role in the conversation. The system message typically guides the model's behavior, sets the tone, or specifies desired output from the model. By utilizing the system message effectively, users can steer the model towards generating more accurate and relevant responses.\n\nFor example:\n\n> You are an experienced AI engineer and helpful assistant.\n\n> You are a friendly and knowledgeable chatbot.\n\n### Key `temperature`\n\nThe sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, the model will use log probability to automatically increase the temperature until certain thresholds are hit.\n\nYou can pick a value between 0 and 2. For example:\n\n- `0.1`: Low temperature, extremely conservative and deterministic\n- `0.5`: Medium temperature, balanced between conservative and creative\n- `1.0`: High temperature, creative and bit random\n- `1.5`: Very high temperature, extremely creative and often chaotic and unpredictable\n- `2.0`: Maximum temperature, completely random and unpredictable, for some extreme creative use cases\n\n# The assistant\n\nTake this description of the persona:\n\n> {personaDescription}",resultingParameterName:"modelRequirements",format:"JSON",dependentParameterNames:["availableModelNames","personaDescription"]}],personas:[],preparations:[],knowledgeSources:[],knowledgePieces:[],sources:[{type:"BOOK",path:null,content:"# Prepare Persona\n\n- PIPELINE URL `https://promptbook.studio/promptbook/prepare-persona.book`\n- INPUT PARAMETER `{availableModelNames}` List of available model names separated by comma (,)\n- INPUT PARAMETER `{personaDescription}` Description of the persona\n- OUTPUT PARAMETER `{modelRequirements}` Specific requirements for the model\n\n## Make modelRequirements\n\n- FORMAT JSON\n\n```markdown\nYou are experienced AI engineer, you need to create virtual assistant.\nWrite\n\n## Example\n\n\\`\\`\\`json\n{\n\"modelName\": \"gpt-4o\",\n\"systemMessage\": \"You are experienced AI engineer and helpfull assistant.\",\n\"temperature\": 0.7\n}\n\\`\\`\\`\n\n## Instructions\n\n- Your output format is JSON object\n- Write just the JSON object, no other text should be present\n- It contains the following keys:\n - `modelName`: The name of the model to use\n - `systemMessage`: The system message to provide context to the model\n - `temperature`: The sampling temperature to use\n\n### Key `modelName`\n\nPick from the following models:\n\n- {availableModelNames}\n\n### Key `systemMessage`\n\nThe system message is used to communicate instructions or provide context to the model at the beginning of a conversation. It is displayed in a different format compared to user messages, helping the model understand its role in the conversation. The system message typically guides the model's behavior, sets the tone, or specifies desired output from the model. By utilizing the system message effectively, users can steer the model towards generating more accurate and relevant responses.\n\nFor example:\n\n> You are an experienced AI engineer and helpful assistant.\n\n> You are a friendly and knowledgeable chatbot.\n\n### Key `temperature`\n\nThe sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, the model will use log probability to automatically increase the temperature until certain thresholds are hit.\n\nYou can pick a value between 0 and 2. For example:\n\n- `0.1`: Low temperature, extremely conservative and deterministic\n- `0.5`: Medium temperature, balanced between conservative and creative\n- `1.0`: High temperature, creative and bit random\n- `1.5`: Very high temperature, extremely creative and often chaotic and unpredictable\n- `2.0`: Maximum temperature, completely random and unpredictable, for some extreme creative use cases\n\n# The assistant\n\nTake this description of the persona:\n\n> {personaDescription}\n```\n\n`-> {modelRequirements}`\n"}],sourceFile:"./books/prepare-persona.book"},{title:"Prepare Title",pipelineUrl:"https://promptbook.studio/promptbook/prepare-title.book",formfactorName:"GENERIC",parameters:[{name:"book",description:"The book to prepare the title for",isInput:true,isOutput:false},{name:"title",description:"Best title for the book",isInput:false,isOutput:true}],tasks:[{taskType:"PROMPT_TASK",name:"make-title",title:"Make title",content:"Make best title for given text which describes the workflow:\n\n## Rules\n\n- Write just title, nothing else\n- Title should be concise and clear - Write maximum ideally 2 words, maximum 5 words\n- Title starts with emoticon\n- Title should not mention the input and output of the workflow but the main purpose of the workflow\n _For example, not \"✍ Convert Knowledge-piece to title\" but \"✍ Title\"_\n\n## The workflow\n\n> {book}",resultingParameterName:"title",expectations:{words:{min:1,max:8},lines:{min:1,max:1}},dependentParameterNames:["book"]}],personas:[],preparations:[],knowledgeSources:[],knowledgePieces:[],sources:[{type:"BOOK",path:null,content:"# Prepare Title\n\n- PIPELINE URL `https://promptbook.studio/promptbook/prepare-title.book`\n- INPUT PARAMETER `{book}` The book to prepare the title for\n- OUTPUT PARAMETER `{title}` Best title for the book\n\n## Make title\n\n- EXPECT MIN 1 Word\n- EXPECT MAX 8 Words\n- EXPECT EXACTLY 1 Line\n\n```markdown\nMake best title for given text which describes the workflow:\n\n## Rules\n\n- Write just title, nothing else\n- Title should be concise and clear - Write maximum ideally 2 words, maximum 5 words\n- Title starts with emoticon\n- Title should not mention the input and output of the workflow but the main purpose of the workflow\n _For example, not \"✍ Convert Knowledge-piece to title\" but \"✍ Title\"_\n\n## The workflow\n\n> {book}\n```\n\n`-> {title}`\n"}],sourceFile:"./books/prepare-title.book"}];
|
|
3677
|
-
|
|
3678
|
-
/**
|
|
3679
|
-
* Checks if value is valid email
|
|
3680
|
-
*
|
|
3681
|
-
* @public exported from `@promptbook/utils`
|
|
3682
|
-
*/
|
|
3683
|
-
function isValidEmail(email) {
|
|
3684
|
-
if (typeof email !== 'string') {
|
|
3685
|
-
return false;
|
|
3686
|
-
}
|
|
3687
|
-
if (email.split('\n').length > 1) {
|
|
3688
|
-
return false;
|
|
3689
|
-
}
|
|
3690
|
-
return /^.+@.+\..+$/.test(email);
|
|
3691
|
-
}
|
|
3692
|
-
|
|
3693
3676
|
/**
|
|
3694
3677
|
* This error indicates that the promptbook in a markdown format cannot be parsed into a valid promptbook object
|
|
3695
3678
|
*
|
|
@@ -3710,677 +3693,749 @@ var ParseError = /** @class */ (function (_super) {
|
|
|
3710
3693
|
*/
|
|
3711
3694
|
|
|
3712
3695
|
/**
|
|
3713
|
-
*
|
|
3696
|
+
* This error indicates that the promptbook object has valid syntax (=can be parsed) but contains logical errors (like circular dependencies)
|
|
3714
3697
|
*
|
|
3715
|
-
* @public exported from `@promptbook/
|
|
3698
|
+
* @public exported from `@promptbook/core`
|
|
3716
3699
|
*/
|
|
3717
|
-
|
|
3718
|
-
|
|
3719
|
-
|
|
3720
|
-
|
|
3721
|
-
|
|
3722
|
-
|
|
3723
|
-
|
|
3724
|
-
throw error;
|
|
3725
|
-
}
|
|
3726
|
-
if (error.message.includes('Unexpected token')) {
|
|
3727
|
-
return false;
|
|
3728
|
-
}
|
|
3729
|
-
return false;
|
|
3700
|
+
var PipelineLogicError = /** @class */ (function (_super) {
|
|
3701
|
+
__extends(PipelineLogicError, _super);
|
|
3702
|
+
function PipelineLogicError(message) {
|
|
3703
|
+
var _this = _super.call(this, message) || this;
|
|
3704
|
+
_this.name = 'PipelineLogicError';
|
|
3705
|
+
Object.setPrototypeOf(_this, PipelineLogicError.prototype);
|
|
3706
|
+
return _this;
|
|
3730
3707
|
}
|
|
3731
|
-
|
|
3708
|
+
return PipelineLogicError;
|
|
3709
|
+
}(Error));
|
|
3732
3710
|
|
|
3733
3711
|
/**
|
|
3734
|
-
*
|
|
3735
|
-
* It does not check if the string is fully logically correct, but if it is a string that can be a pipeline string or the string looks completely different.
|
|
3712
|
+
* Tests if given string is valid semantic version
|
|
3736
3713
|
*
|
|
3737
|
-
*
|
|
3738
|
-
*
|
|
3739
|
-
*
|
|
3740
|
-
*
|
|
3714
|
+
* Note: There are two simmilar functions:
|
|
3715
|
+
* - `isValidSemanticVersion` which tests any semantic version
|
|
3716
|
+
* - `isValidPromptbookVersion` *(this one)* which tests just Promptbook versions
|
|
3717
|
+
*
|
|
3718
|
+
* @public exported from `@promptbook/utils`
|
|
3741
3719
|
*/
|
|
3742
|
-
function
|
|
3743
|
-
if (
|
|
3744
|
-
|
|
3745
|
-
}
|
|
3746
|
-
else if (isValidUrl(pipelineString)) {
|
|
3747
|
-
throw new ParseError("Expected a book, but got just the URL \"".concat(pipelineString, "\""));
|
|
3748
|
-
}
|
|
3749
|
-
else if (isValidFilePath(pipelineString)) {
|
|
3750
|
-
throw new ParseError("Expected a book, but got just the file path \"".concat(pipelineString, "\""));
|
|
3720
|
+
function isValidSemanticVersion(version) {
|
|
3721
|
+
if (typeof version !== 'string') {
|
|
3722
|
+
return false;
|
|
3751
3723
|
}
|
|
3752
|
-
|
|
3753
|
-
|
|
3724
|
+
if (version.startsWith('0.0.0')) {
|
|
3725
|
+
return false;
|
|
3754
3726
|
}
|
|
3755
|
-
|
|
3756
|
-
return pipelineString;
|
|
3727
|
+
return /^\d+\.\d+\.\d+(-\d+)?$/i.test(version);
|
|
3757
3728
|
}
|
|
3758
|
-
/**
|
|
3759
|
-
* TODO: [🧠][🈴] Where is the best location for this file
|
|
3760
|
-
*/
|
|
3761
3729
|
|
|
3762
3730
|
/**
|
|
3763
|
-
*
|
|
3731
|
+
* Tests if given string is valid promptbook version
|
|
3732
|
+
* It looks into list of known promptbook versions.
|
|
3764
3733
|
*
|
|
3765
|
-
* @
|
|
3766
|
-
*
|
|
3767
|
-
*
|
|
3734
|
+
* @see https://www.npmjs.com/package/promptbook?activeTab=versions
|
|
3735
|
+
* 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.
|
|
3736
|
+
* Note: There are two simmilar functions:
|
|
3737
|
+
* - `isValidSemanticVersion` which tests any semantic version
|
|
3738
|
+
* - `isValidPromptbookVersion` *(this one)* which tests just Promptbook versions
|
|
3739
|
+
*
|
|
3740
|
+
* @public exported from `@promptbook/utils`
|
|
3768
3741
|
*/
|
|
3769
|
-
function
|
|
3770
|
-
|
|
3771
|
-
return
|
|
3772
|
-
parser: 'markdown',
|
|
3773
|
-
plugins: [parserHtml],
|
|
3774
|
-
// TODO: DRY - make some import or auto-copy of .prettierrc
|
|
3775
|
-
endOfLine: 'lf',
|
|
3776
|
-
tabWidth: 4,
|
|
3777
|
-
singleQuote: true,
|
|
3778
|
-
trailingComma: 'all',
|
|
3779
|
-
arrowParens: 'always',
|
|
3780
|
-
printWidth: 120,
|
|
3781
|
-
htmlWhitespaceSensitivity: 'ignore',
|
|
3782
|
-
jsxBracketSameLine: false,
|
|
3783
|
-
bracketSpacing: true,
|
|
3784
|
-
});
|
|
3742
|
+
function isValidPromptbookVersion(version) {
|
|
3743
|
+
if (!isValidSemanticVersion(version)) {
|
|
3744
|
+
return false;
|
|
3785
3745
|
}
|
|
3786
|
-
|
|
3787
|
-
|
|
3788
|
-
console.error('There was an error with prettifying the markdown, using the original as the fallback', {
|
|
3789
|
-
error: error,
|
|
3790
|
-
html: content,
|
|
3791
|
-
});
|
|
3792
|
-
return content;
|
|
3746
|
+
if ( /* version === '1.0.0' || */version === '2.0.0' || version === '3.0.0') {
|
|
3747
|
+
return false;
|
|
3793
3748
|
}
|
|
3749
|
+
// <- TODO: [main] !!3 Check isValidPromptbookVersion against PROMPTBOOK_ENGINE_VERSIONS
|
|
3750
|
+
return true;
|
|
3794
3751
|
}
|
|
3795
3752
|
|
|
3796
3753
|
/**
|
|
3797
|
-
*
|
|
3754
|
+
* Tests if given string is valid pipeline URL URL.
|
|
3755
|
+
*
|
|
3756
|
+
* Note: There are two simmilar functions:
|
|
3757
|
+
* - `isValidUrl` which tests any URL
|
|
3758
|
+
* - `isValidPipelineUrl` *(this one)* which tests just pipeline URL
|
|
3798
3759
|
*
|
|
3799
3760
|
* @public exported from `@promptbook/utils`
|
|
3800
3761
|
*/
|
|
3801
|
-
function
|
|
3802
|
-
|
|
3762
|
+
function isValidPipelineUrl(url) {
|
|
3763
|
+
if (!isValidUrl(url)) {
|
|
3764
|
+
return false;
|
|
3765
|
+
}
|
|
3766
|
+
if (!url.startsWith('https://') && !url.startsWith('http://') /* <- Note: [👣] */) {
|
|
3767
|
+
return false;
|
|
3768
|
+
}
|
|
3769
|
+
if (url.includes('#')) {
|
|
3770
|
+
// TODO: [🐠]
|
|
3771
|
+
return false;
|
|
3772
|
+
}
|
|
3773
|
+
/*
|
|
3774
|
+
Note: [👣][🧠] Is it secure to allow pipeline URLs on private and unsecured networks?
|
|
3775
|
+
if (isUrlOnPrivateNetwork(url)) {
|
|
3776
|
+
return false;
|
|
3777
|
+
}
|
|
3778
|
+
*/
|
|
3779
|
+
return true;
|
|
3803
3780
|
}
|
|
3781
|
+
/**
|
|
3782
|
+
* TODO: [🐠] Maybe more info why the URL is invalid
|
|
3783
|
+
*/
|
|
3804
3784
|
|
|
3805
3785
|
/**
|
|
3806
|
-
*
|
|
3786
|
+
* Validates PipelineJson if it is logically valid
|
|
3807
3787
|
*
|
|
3808
|
-
*
|
|
3809
|
-
*
|
|
3810
|
-
*
|
|
3788
|
+
* It checks:
|
|
3789
|
+
* - if it has correct parameters dependency
|
|
3790
|
+
*
|
|
3791
|
+
* It does NOT check:
|
|
3792
|
+
* - if it is valid json
|
|
3793
|
+
* - if it is meaningful
|
|
3794
|
+
*
|
|
3795
|
+
* @param pipeline valid or invalid PipelineJson
|
|
3796
|
+
* @returns the same pipeline if it is logically valid
|
|
3797
|
+
* @throws {PipelineLogicError} on logical error in the pipeline
|
|
3811
3798
|
* @public exported from `@promptbook/core`
|
|
3812
3799
|
*/
|
|
3813
|
-
function
|
|
3814
|
-
|
|
3815
|
-
|
|
3816
|
-
var pipelineString = "# ".concat(title);
|
|
3817
|
-
if (description) {
|
|
3818
|
-
pipelineString += '\n\n';
|
|
3819
|
-
pipelineString += description;
|
|
3820
|
-
}
|
|
3821
|
-
var commands = [];
|
|
3822
|
-
if (pipelineUrl) {
|
|
3823
|
-
commands.push("PIPELINE URL ".concat(pipelineUrl));
|
|
3824
|
-
}
|
|
3825
|
-
if (bookVersion !== "undefined") {
|
|
3826
|
-
commands.push("BOOK VERSION ".concat(bookVersion));
|
|
3827
|
-
}
|
|
3828
|
-
// TODO: [main] !!5 This increases size of the bundle and is probbably not necessary
|
|
3829
|
-
pipelineString = prettifyMarkdown(pipelineString);
|
|
3830
|
-
try {
|
|
3831
|
-
for (var _g = __values(parameters.filter(function (_a) {
|
|
3832
|
-
var isInput = _a.isInput;
|
|
3833
|
-
return isInput;
|
|
3834
|
-
})), _h = _g.next(); !_h.done; _h = _g.next()) {
|
|
3835
|
-
var parameter = _h.value;
|
|
3836
|
-
commands.push("INPUT PARAMETER ".concat(taskParameterJsonToString(parameter)));
|
|
3837
|
-
}
|
|
3800
|
+
function validatePipeline(pipeline) {
|
|
3801
|
+
if (IS_PIPELINE_LOGIC_VALIDATED) {
|
|
3802
|
+
validatePipeline_InnerFunction(pipeline);
|
|
3838
3803
|
}
|
|
3839
|
-
|
|
3840
|
-
finally {
|
|
3804
|
+
else {
|
|
3841
3805
|
try {
|
|
3842
|
-
|
|
3806
|
+
validatePipeline_InnerFunction(pipeline);
|
|
3843
3807
|
}
|
|
3844
|
-
|
|
3845
|
-
|
|
3846
|
-
|
|
3847
|
-
|
|
3848
|
-
|
|
3849
|
-
return isOutput;
|
|
3850
|
-
})), _k = _j.next(); !_k.done; _k = _j.next()) {
|
|
3851
|
-
var parameter = _k.value;
|
|
3852
|
-
commands.push("OUTPUT PARAMETER ".concat(taskParameterJsonToString(parameter)));
|
|
3808
|
+
catch (error) {
|
|
3809
|
+
if (!(error instanceof PipelineLogicError)) {
|
|
3810
|
+
throw error;
|
|
3811
|
+
}
|
|
3812
|
+
console.error(spaceTrim$1(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 "); }));
|
|
3853
3813
|
}
|
|
3854
3814
|
}
|
|
3855
|
-
|
|
3856
|
-
|
|
3857
|
-
|
|
3858
|
-
|
|
3815
|
+
return pipeline;
|
|
3816
|
+
}
|
|
3817
|
+
/**
|
|
3818
|
+
* @private internal function for `validatePipeline`
|
|
3819
|
+
*/
|
|
3820
|
+
function validatePipeline_InnerFunction(pipeline) {
|
|
3821
|
+
// TODO: [🧠] Maybe test if promptbook is a promise and make specific error case for that
|
|
3822
|
+
var e_1, _a, e_2, _b, e_3, _c;
|
|
3823
|
+
var pipelineIdentification = (function () {
|
|
3824
|
+
// Note: This is a 😐 implementation of [🚞]
|
|
3825
|
+
var _ = [];
|
|
3826
|
+
if (pipeline.sourceFile !== undefined) {
|
|
3827
|
+
_.push("File: ".concat(pipeline.sourceFile));
|
|
3859
3828
|
}
|
|
3860
|
-
|
|
3829
|
+
if (pipeline.pipelineUrl !== undefined) {
|
|
3830
|
+
_.push("Url: ".concat(pipeline.pipelineUrl));
|
|
3831
|
+
}
|
|
3832
|
+
return _.join('\n');
|
|
3833
|
+
})();
|
|
3834
|
+
if (pipeline.pipelineUrl !== undefined && !isValidPipelineUrl(pipeline.pipelineUrl)) {
|
|
3835
|
+
// <- Note: [🚲]
|
|
3836
|
+
throw new PipelineLogicError(spaceTrim$1(function (block) { return "\n Invalid promptbook URL \"".concat(pipeline.pipelineUrl, "\"\n\n ").concat(block(pipelineIdentification), "\n "); }));
|
|
3861
3837
|
}
|
|
3862
|
-
|
|
3863
|
-
|
|
3864
|
-
|
|
3865
|
-
|
|
3866
|
-
|
|
3867
|
-
|
|
3868
|
-
|
|
3869
|
-
|
|
3870
|
-
|
|
3871
|
-
|
|
3872
|
-
|
|
3873
|
-
|
|
3874
|
-
|
|
3875
|
-
|
|
3876
|
-
|
|
3877
|
-
|
|
3878
|
-
|
|
3879
|
-
|
|
3880
|
-
|
|
3881
|
-
|
|
3882
|
-
|
|
3883
|
-
|
|
3884
|
-
|
|
3885
|
-
|
|
3886
|
-
|
|
3887
|
-
|
|
3888
|
-
|
|
3889
|
-
|
|
3890
|
-
|
|
3891
|
-
|
|
3892
|
-
|
|
3893
|
-
|
|
3894
|
-
|
|
3838
|
+
if (pipeline.bookVersion !== undefined && !isValidPromptbookVersion(pipeline.bookVersion)) {
|
|
3839
|
+
// <- Note: [🚲]
|
|
3840
|
+
throw new PipelineLogicError(spaceTrim$1(function (block) { return "\n Invalid Promptbook Version \"".concat(pipeline.bookVersion, "\"\n\n ").concat(block(pipelineIdentification), "\n "); }));
|
|
3841
|
+
}
|
|
3842
|
+
// TODO: [🧠] Maybe do here some propper JSON-schema / ZOD checking
|
|
3843
|
+
if (!Array.isArray(pipeline.parameters)) {
|
|
3844
|
+
// TODO: [🧠] what is the correct error tp throw - maybe PromptbookSchemaError
|
|
3845
|
+
throw new ParseError(spaceTrim$1(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 "); }));
|
|
3846
|
+
}
|
|
3847
|
+
// TODO: [🧠] Maybe do here some propper JSON-schema / ZOD checking
|
|
3848
|
+
if (!Array.isArray(pipeline.tasks)) {
|
|
3849
|
+
// TODO: [🧠] what is the correct error tp throw - maybe PromptbookSchemaError
|
|
3850
|
+
throw new ParseError(spaceTrim$1(function (block) { return "\n Pipeline is valid JSON but with wrong structure\n\n `PipelineJson.tasks` expected to be an array, but got ".concat(typeof pipeline.tasks, "\n\n ").concat(block(pipelineIdentification), "\n "); }));
|
|
3851
|
+
}
|
|
3852
|
+
var _loop_1 = function (parameter) {
|
|
3853
|
+
if (parameter.isInput && parameter.isOutput) {
|
|
3854
|
+
throw new PipelineLogicError(spaceTrim$1(function (block) { return "\n\n Parameter `{".concat(parameter.name, "}` can not be both input and output\n\n ").concat(block(pipelineIdentification), "\n "); }));
|
|
3855
|
+
}
|
|
3856
|
+
// Note: Testing that parameter is either intermediate or output BUT not created and unused
|
|
3857
|
+
if (!parameter.isInput &&
|
|
3858
|
+
!parameter.isOutput &&
|
|
3859
|
+
!pipeline.tasks.some(function (task) { return task.dependentParameterNames.includes(parameter.name); })) {
|
|
3860
|
+
throw new PipelineLogicError(spaceTrim$1(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 "); }));
|
|
3861
|
+
}
|
|
3862
|
+
// Note: Testing that parameter is either input or result of some task
|
|
3863
|
+
if (!parameter.isInput && !pipeline.tasks.some(function (task) { return task.resultingParameterName === parameter.name; })) {
|
|
3864
|
+
throw new PipelineLogicError(spaceTrim$1(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 task that results in `-> {").concat(parameter.name, "}`\n\n ").concat(block(pipelineIdentification), "\n "); }));
|
|
3865
|
+
}
|
|
3866
|
+
};
|
|
3867
|
+
try {
|
|
3868
|
+
/*
|
|
3869
|
+
TODO: [🧠][🅾] Should be empty pipeline valid or not
|
|
3870
|
+
// Note: Check that pipeline has some tasks
|
|
3871
|
+
if (pipeline.tasks.length === 0) {
|
|
3872
|
+
throw new PipelineLogicError(
|
|
3873
|
+
spaceTrim(
|
|
3874
|
+
(block) => `
|
|
3875
|
+
Pipeline must have at least one task
|
|
3876
|
+
|
|
3877
|
+
${block(pipelineIdentification)}
|
|
3878
|
+
`,
|
|
3879
|
+
),
|
|
3880
|
+
);
|
|
3881
|
+
}
|
|
3882
|
+
*/
|
|
3883
|
+
// Note: Check each parameter individually
|
|
3884
|
+
for (var _d = __values(pipeline.parameters), _e = _d.next(); !_e.done; _e = _d.next()) {
|
|
3885
|
+
var parameter = _e.value;
|
|
3886
|
+
_loop_1(parameter);
|
|
3887
|
+
}
|
|
3888
|
+
}
|
|
3889
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
3890
|
+
finally {
|
|
3891
|
+
try {
|
|
3892
|
+
if (_e && !_e.done && (_a = _d.return)) _a.call(_d);
|
|
3893
|
+
}
|
|
3894
|
+
finally { if (e_1) throw e_1.error; }
|
|
3895
|
+
}
|
|
3896
|
+
// Note: All input parameters are defined - so that they can be used as result of some task
|
|
3897
|
+
var definedParameters = new Set(pipeline.parameters.filter(function (_a) {
|
|
3898
|
+
var isInput = _a.isInput;
|
|
3899
|
+
return isInput;
|
|
3900
|
+
}).map(function (_a) {
|
|
3901
|
+
var name = _a.name;
|
|
3902
|
+
return name;
|
|
3903
|
+
}));
|
|
3904
|
+
var _loop_2 = function (task) {
|
|
3905
|
+
var e_4, _h, e_5, _j;
|
|
3906
|
+
if (definedParameters.has(task.resultingParameterName)) {
|
|
3907
|
+
throw new PipelineLogicError(spaceTrim$1(function (block) { return "\n Parameter `{".concat(task.resultingParameterName, "}` is defined multiple times\n\n ").concat(block(pipelineIdentification), "\n "); }));
|
|
3908
|
+
}
|
|
3909
|
+
if (RESERVED_PARAMETER_NAMES.includes(task.resultingParameterName)) {
|
|
3910
|
+
throw new PipelineLogicError(spaceTrim$1(function (block) { return "\n Parameter name {".concat(task.resultingParameterName, "} is reserved, please use different name\n\n ").concat(block(pipelineIdentification), "\n "); }));
|
|
3911
|
+
}
|
|
3912
|
+
definedParameters.add(task.resultingParameterName);
|
|
3913
|
+
if (task.jokerParameterNames && task.jokerParameterNames.length > 0) {
|
|
3914
|
+
if (!task.format &&
|
|
3915
|
+
!task.expectations /* <- TODO: Require at least 1 -> min <- expectation to use jokers */) {
|
|
3916
|
+
throw new PipelineLogicError(spaceTrim$1(function (block) { return "\n Joker parameters are used for {".concat(task.resultingParameterName, "} but no expectations are defined\n\n ").concat(block(pipelineIdentification), "\n "); }));
|
|
3895
3917
|
}
|
|
3896
|
-
|
|
3897
|
-
|
|
3898
|
-
|
|
3899
|
-
contentLanguage = task.contentLanguage;
|
|
3918
|
+
var _loop_4 = function (joker) {
|
|
3919
|
+
if (!task.dependentParameterNames.includes(joker)) {
|
|
3920
|
+
throw new PipelineLogicError(spaceTrim$1(function (block) { return "\n Parameter `{".concat(joker, "}` is used for {").concat(task.resultingParameterName, "} as joker but not in `dependentParameterNames`\n\n ").concat(block(pipelineIdentification), "\n "); }));
|
|
3900
3921
|
}
|
|
3901
|
-
|
|
3902
|
-
|
|
3922
|
+
};
|
|
3923
|
+
try {
|
|
3924
|
+
for (var _k = (e_4 = void 0, __values(task.jokerParameterNames)), _l = _k.next(); !_l.done; _l = _k.next()) {
|
|
3925
|
+
var joker = _l.value;
|
|
3926
|
+
_loop_4(joker);
|
|
3903
3927
|
}
|
|
3904
3928
|
}
|
|
3905
|
-
|
|
3906
|
-
|
|
3907
|
-
// Note: Nothing special here
|
|
3908
|
-
} // <- }else if([🅱]
|
|
3909
|
-
if (jokers) {
|
|
3929
|
+
catch (e_4_1) { e_4 = { error: e_4_1 }; }
|
|
3930
|
+
finally {
|
|
3910
3931
|
try {
|
|
3911
|
-
|
|
3912
|
-
var joker = jokers_1_1.value;
|
|
3913
|
-
commands_1.push("JOKER {".concat(joker, "}"));
|
|
3914
|
-
}
|
|
3915
|
-
}
|
|
3916
|
-
catch (e_4_1) { e_4 = { error: e_4_1 }; }
|
|
3917
|
-
finally {
|
|
3918
|
-
try {
|
|
3919
|
-
if (jokers_1_1 && !jokers_1_1.done && (_d = jokers_1.return)) _d.call(jokers_1);
|
|
3920
|
-
}
|
|
3921
|
-
finally { if (e_4) throw e_4.error; }
|
|
3932
|
+
if (_l && !_l.done && (_h = _k.return)) _h.call(_k);
|
|
3922
3933
|
}
|
|
3923
|
-
|
|
3924
|
-
|
|
3925
|
-
|
|
3926
|
-
|
|
3927
|
-
|
|
3928
|
-
|
|
3929
|
-
}
|
|
3934
|
+
finally { if (e_4) throw e_4.error; }
|
|
3935
|
+
}
|
|
3936
|
+
}
|
|
3937
|
+
if (task.expectations) {
|
|
3938
|
+
var _loop_5 = function (unit, min, max) {
|
|
3939
|
+
if (min !== undefined && max !== undefined && min > max) {
|
|
3940
|
+
throw new PipelineLogicError(spaceTrim$1(function (block) { return "\n Min expectation (=".concat(min, ") of ").concat(unit, " is higher than max expectation (=").concat(max, ")\n\n ").concat(block(pipelineIdentification), "\n "); }));
|
|
3930
3941
|
}
|
|
3931
|
-
|
|
3932
|
-
|
|
3933
|
-
try {
|
|
3934
|
-
if (postprocessing_1_1 && !postprocessing_1_1.done && (_e = postprocessing_1.return)) _e.call(postprocessing_1);
|
|
3935
|
-
}
|
|
3936
|
-
finally { if (e_5) throw e_5.error; }
|
|
3942
|
+
if (min !== undefined && min < 0) {
|
|
3943
|
+
throw new PipelineLogicError(spaceTrim$1(function (block) { return "\n Min expectation of ".concat(unit, " must be zero or positive\n\n ").concat(block(pipelineIdentification), "\n "); }));
|
|
3937
3944
|
}
|
|
3938
|
-
|
|
3939
|
-
|
|
3940
|
-
try {
|
|
3941
|
-
for (var _m = (e_6 = void 0, __values(Object.entries(expectations))), _o = _m.next(); !_o.done; _o = _m.next()) {
|
|
3942
|
-
var _p = __read(_o.value, 2), unit = _p[0], _q = _p[1], min = _q.min, max = _q.max;
|
|
3943
|
-
if (min === max) {
|
|
3944
|
-
commands_1.push("EXPECT EXACTLY ".concat(min, " ").concat(capitalize(unit + (min > 1 ? 's' : ''))));
|
|
3945
|
-
}
|
|
3946
|
-
else {
|
|
3947
|
-
if (min !== undefined) {
|
|
3948
|
-
commands_1.push("EXPECT MIN ".concat(min, " ").concat(capitalize(unit + (min > 1 ? 's' : ''))));
|
|
3949
|
-
} /* not else */
|
|
3950
|
-
if (max !== undefined) {
|
|
3951
|
-
commands_1.push("EXPECT MAX ".concat(max, " ").concat(capitalize(unit + (max > 1 ? 's' : ''))));
|
|
3952
|
-
}
|
|
3953
|
-
}
|
|
3954
|
-
}
|
|
3945
|
+
if (max !== undefined && max <= 0) {
|
|
3946
|
+
throw new PipelineLogicError(spaceTrim$1(function (block) { return "\n Max expectation of ".concat(unit, " must be positive\n\n ").concat(block(pipelineIdentification), "\n "); }));
|
|
3955
3947
|
}
|
|
3956
|
-
|
|
3957
|
-
|
|
3958
|
-
|
|
3959
|
-
|
|
3960
|
-
|
|
3961
|
-
finally { if (e_6) throw e_6.error; }
|
|
3948
|
+
};
|
|
3949
|
+
try {
|
|
3950
|
+
for (var _m = (e_5 = void 0, __values(Object.entries(task.expectations))), _o = _m.next(); !_o.done; _o = _m.next()) {
|
|
3951
|
+
var _p = __read(_o.value, 2), unit = _p[0], _q = _p[1], min = _q.min, max = _q.max;
|
|
3952
|
+
_loop_5(unit, min, max);
|
|
3962
3953
|
}
|
|
3963
|
-
}
|
|
3964
|
-
|
|
3965
|
-
|
|
3966
|
-
|
|
3967
|
-
|
|
3954
|
+
}
|
|
3955
|
+
catch (e_5_1) { e_5 = { error: e_5_1 }; }
|
|
3956
|
+
finally {
|
|
3957
|
+
try {
|
|
3958
|
+
if (_o && !_o.done && (_j = _m.return)) _j.call(_m);
|
|
3968
3959
|
}
|
|
3969
|
-
|
|
3970
|
-
|
|
3971
|
-
|
|
3972
|
-
|
|
3973
|
-
|
|
3974
|
-
|
|
3975
|
-
|
|
3976
|
-
|
|
3977
|
-
|
|
3978
|
-
|
|
3979
|
-
|
|
3980
|
-
|
|
3981
|
-
|
|
3960
|
+
finally { if (e_5) throw e_5.error; }
|
|
3961
|
+
}
|
|
3962
|
+
}
|
|
3963
|
+
};
|
|
3964
|
+
try {
|
|
3965
|
+
// Note: Checking each task individually
|
|
3966
|
+
for (var _f = __values(pipeline.tasks), _g = _f.next(); !_g.done; _g = _f.next()) {
|
|
3967
|
+
var task = _g.value;
|
|
3968
|
+
_loop_2(task);
|
|
3969
|
+
}
|
|
3970
|
+
}
|
|
3971
|
+
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
3972
|
+
finally {
|
|
3973
|
+
try {
|
|
3974
|
+
if (_g && !_g.done && (_b = _f.return)) _b.call(_f);
|
|
3975
|
+
}
|
|
3976
|
+
finally { if (e_2) throw e_2.error; }
|
|
3977
|
+
}
|
|
3978
|
+
// Note: Detect circular dependencies
|
|
3979
|
+
var resovedParameters = pipeline.parameters
|
|
3980
|
+
.filter(function (_a) {
|
|
3981
|
+
var isInput = _a.isInput;
|
|
3982
|
+
return isInput;
|
|
3983
|
+
})
|
|
3984
|
+
.map(function (_a) {
|
|
3985
|
+
var name = _a.name;
|
|
3986
|
+
return name;
|
|
3987
|
+
});
|
|
3988
|
+
try {
|
|
3989
|
+
// Note: All reserved parameters are resolved
|
|
3990
|
+
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()) {
|
|
3991
|
+
var reservedParameterName = RESERVED_PARAMETER_NAMES_1_1.value;
|
|
3992
|
+
resovedParameters = __spreadArray(__spreadArray([], __read(resovedParameters), false), [reservedParameterName], false);
|
|
3982
3993
|
}
|
|
3983
3994
|
}
|
|
3984
3995
|
catch (e_3_1) { e_3 = { error: e_3_1 }; }
|
|
3985
3996
|
finally {
|
|
3986
3997
|
try {
|
|
3987
|
-
if (
|
|
3998
|
+
if (RESERVED_PARAMETER_NAMES_1_1 && !RESERVED_PARAMETER_NAMES_1_1.done && (_c = RESERVED_PARAMETER_NAMES_1.return)) _c.call(RESERVED_PARAMETER_NAMES_1);
|
|
3988
3999
|
}
|
|
3989
4000
|
finally { if (e_3) throw e_3.error; }
|
|
3990
4001
|
}
|
|
3991
|
-
|
|
4002
|
+
var unresovedTasks = __spreadArray([], __read(pipeline.tasks), false);
|
|
4003
|
+
var loopLimit = LOOP_LIMIT;
|
|
4004
|
+
var _loop_3 = function () {
|
|
4005
|
+
if (loopLimit-- < 0) {
|
|
4006
|
+
// Note: Really UnexpectedError not LimitReachedError - this should not happen and be caught below
|
|
4007
|
+
throw new UnexpectedError(spaceTrim$1(function (block) { return "\n Loop limit reached during detection of circular dependencies in `validatePipeline`\n\n ".concat(block(pipelineIdentification), "\n "); }));
|
|
4008
|
+
}
|
|
4009
|
+
var currentlyResovedTasks = unresovedTasks.filter(function (task) {
|
|
4010
|
+
return task.dependentParameterNames.every(function (name) { return resovedParameters.includes(name); });
|
|
4011
|
+
});
|
|
4012
|
+
if (currentlyResovedTasks.length === 0) {
|
|
4013
|
+
throw new PipelineLogicError(
|
|
4014
|
+
// TODO: [🐎] DRY
|
|
4015
|
+
spaceTrim$1(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(unresovedTasks
|
|
4016
|
+
.map(function (_a) {
|
|
4017
|
+
var resultingParameterName = _a.resultingParameterName, dependentParameterNames = _a.dependentParameterNames;
|
|
4018
|
+
return "- Parameter `{".concat(resultingParameterName, "}` which depends on ").concat(dependentParameterNames
|
|
4019
|
+
.map(function (dependentParameterName) { return "`{".concat(dependentParameterName, "}`"); })
|
|
4020
|
+
.join(' and '));
|
|
4021
|
+
})
|
|
4022
|
+
.join('\n')), "\n\n **Resolved:**\n ").concat(block(resovedParameters
|
|
4023
|
+
.filter(function (name) {
|
|
4024
|
+
return !RESERVED_PARAMETER_NAMES.includes(name);
|
|
4025
|
+
})
|
|
4026
|
+
.map(function (name) { return "- Parameter `{".concat(name, "}`"); })
|
|
4027
|
+
.join('\n')), "\n\n\n **Reserved (which are available):**\n ").concat(block(resovedParameters
|
|
4028
|
+
.filter(function (name) {
|
|
4029
|
+
return RESERVED_PARAMETER_NAMES.includes(name);
|
|
4030
|
+
})
|
|
4031
|
+
.map(function (name) { return "- Parameter `{".concat(name, "}`"); })
|
|
4032
|
+
.join('\n')), "\n\n\n "); }));
|
|
4033
|
+
}
|
|
4034
|
+
resovedParameters = __spreadArray(__spreadArray([], __read(resovedParameters), false), __read(currentlyResovedTasks.map(function (_a) {
|
|
4035
|
+
var resultingParameterName = _a.resultingParameterName;
|
|
4036
|
+
return resultingParameterName;
|
|
4037
|
+
})), false);
|
|
4038
|
+
unresovedTasks = unresovedTasks.filter(function (task) { return !currentlyResovedTasks.includes(task); });
|
|
4039
|
+
};
|
|
4040
|
+
while (unresovedTasks.length > 0) {
|
|
4041
|
+
_loop_3();
|
|
4042
|
+
}
|
|
4043
|
+
// Note: Check that formfactor is corresponding to the pipeline interface
|
|
4044
|
+
// TODO: !!6 Implement this
|
|
4045
|
+
// pipeline.formfactorName
|
|
3992
4046
|
}
|
|
3993
4047
|
/**
|
|
3994
|
-
*
|
|
4048
|
+
* TODO: [🧞♀️] Do not allow joker + foreach
|
|
4049
|
+
* TODO: [🧠] Work with promptbookVersion
|
|
4050
|
+
* TODO: Use here some json-schema, Zod or something similar and change it to:
|
|
4051
|
+
* > /**
|
|
4052
|
+
* > * Validates PipelineJson if it is logically valid.
|
|
4053
|
+
* > *
|
|
4054
|
+
* > * It checks:
|
|
4055
|
+
* > * - it has a valid structure
|
|
4056
|
+
* > * - ...
|
|
4057
|
+
* > ex port function validatePipeline(promptbook: really_unknown): asserts promptbook is PipelineJson {
|
|
3995
4058
|
*/
|
|
3996
|
-
function taskParameterJsonToString(taskParameterJson) {
|
|
3997
|
-
var name = taskParameterJson.name, description = taskParameterJson.description;
|
|
3998
|
-
var parameterString = "{".concat(name, "}");
|
|
3999
|
-
if (description) {
|
|
4000
|
-
parameterString = "".concat(parameterString, " ").concat(description);
|
|
4001
|
-
}
|
|
4002
|
-
return parameterString;
|
|
4003
|
-
}
|
|
4004
4059
|
/**
|
|
4005
|
-
* TODO: [
|
|
4006
|
-
* TODO: [
|
|
4007
|
-
* TODO: [
|
|
4008
|
-
* TODO: [
|
|
4009
|
-
* TODO: [
|
|
4060
|
+
* TODO: [🧳][main] !!4 Validate that all examples match expectations
|
|
4061
|
+
* TODO: [🧳][🐝][main] !!4 Validate that knowledge is valid (non-void)
|
|
4062
|
+
* TODO: [🧳][main] !!4 Validate that persona can be used only with CHAT variant
|
|
4063
|
+
* TODO: [🧳][main] !!4 Validate that parameter with reserved name not used RESERVED_PARAMETER_NAMES
|
|
4064
|
+
* TODO: [🧳][main] !!4 Validate that reserved parameter is not used as joker
|
|
4065
|
+
* TODO: [🧠] Validation not only logic itself but imports around - files and websites and rerefenced pipelines exists
|
|
4066
|
+
* TODO: [🛠] Actions, instruments (and maybe knowledge) => Functions and tools
|
|
4010
4067
|
*/
|
|
4011
4068
|
|
|
4012
4069
|
/**
|
|
4013
|
-
*
|
|
4070
|
+
* Loads the books from the archive file with `.bookc` extension
|
|
4014
4071
|
*
|
|
4015
|
-
* @
|
|
4072
|
+
* @param filePath Path to the archive file with `.bookc` extension
|
|
4073
|
+
* @param fs Filesystem tools
|
|
4074
|
+
* @returns Pipelines loaded from the archive
|
|
4075
|
+
*
|
|
4076
|
+
* @private utility of Prompbook
|
|
4016
4077
|
*/
|
|
4017
|
-
|
|
4018
|
-
|
|
4019
|
-
|
|
4020
|
-
var
|
|
4021
|
-
|
|
4022
|
-
|
|
4023
|
-
|
|
4024
|
-
|
|
4025
|
-
|
|
4026
|
-
}
|
|
4078
|
+
function loadArchive(filePath, fs) {
|
|
4079
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
4080
|
+
var data, archive, indexFile, collectionJson, _a, _b, collectionJson_1, collectionJson_1_1, pipeline;
|
|
4081
|
+
var e_1, _c;
|
|
4082
|
+
return __generator(this, function (_d) {
|
|
4083
|
+
switch (_d.label) {
|
|
4084
|
+
case 0:
|
|
4085
|
+
if (!filePath.endsWith('.bookc')) {
|
|
4086
|
+
throw new UnexpectedError("Archive file must have '.bookc' extension");
|
|
4087
|
+
}
|
|
4088
|
+
return [4 /*yield*/, fs.readFile(filePath)];
|
|
4089
|
+
case 1:
|
|
4090
|
+
data = _d.sent();
|
|
4091
|
+
return [4 /*yield*/, JSZip.loadAsync(data)];
|
|
4092
|
+
case 2:
|
|
4093
|
+
archive = _d.sent();
|
|
4094
|
+
indexFile = archive.file('index.book.json');
|
|
4095
|
+
if (!indexFile) {
|
|
4096
|
+
throw new UnexpectedError("Archive does not contain 'index.book.json' file");
|
|
4097
|
+
}
|
|
4098
|
+
_b = (_a = JSON).parse;
|
|
4099
|
+
return [4 /*yield*/, indexFile.async('text')];
|
|
4100
|
+
case 3:
|
|
4101
|
+
collectionJson = _b.apply(_a, [_d.sent()]);
|
|
4102
|
+
try {
|
|
4103
|
+
for (collectionJson_1 = __values(collectionJson), collectionJson_1_1 = collectionJson_1.next(); !collectionJson_1_1.done; collectionJson_1_1 = collectionJson_1.next()) {
|
|
4104
|
+
pipeline = collectionJson_1_1.value;
|
|
4105
|
+
validatePipeline(pipeline);
|
|
4106
|
+
}
|
|
4107
|
+
}
|
|
4108
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
4109
|
+
finally {
|
|
4110
|
+
try {
|
|
4111
|
+
if (collectionJson_1_1 && !collectionJson_1_1.done && (_c = collectionJson_1.return)) _c.call(collectionJson_1);
|
|
4112
|
+
}
|
|
4113
|
+
finally { if (e_1) throw e_1.error; }
|
|
4114
|
+
}
|
|
4115
|
+
return [2 /*return*/, collectionJson];
|
|
4116
|
+
}
|
|
4117
|
+
});
|
|
4118
|
+
});
|
|
4119
|
+
}
|
|
4120
|
+
/**
|
|
4121
|
+
* Note: [🟢] Code in this file should never be never released in packages that could be imported into browser environment
|
|
4122
|
+
*/
|
|
4123
|
+
|
|
4124
|
+
var PipelineCollection = [{title:"Prepare Knowledge from Markdown",pipelineUrl:"https://promptbook.studio/promptbook/prepare-knowledge-from-markdown.book",formfactorName:"GENERIC",parameters:[{name:"knowledgeContent",description:"Markdown document content",isInput:true,isOutput:false},{name:"knowledgePieces",description:"The knowledge JSON object",isInput:false,isOutput:true}],tasks:[{taskType:"PROMPT_TASK",name:"knowledge",title:"Knowledge",content:"You are experienced data researcher, extract the important knowledge from the document.\n\n# Rules\n\n- Make pieces of information concise, clear, and easy to understand\n- One piece of information should be approximately 1 paragraph\n- Divide the paragraphs by markdown horizontal lines ---\n- Omit irrelevant information\n- Group redundant information\n- Write just extracted information, nothing else\n\n# The document\n\nTake information from this document:\n\n> {knowledgeContent}",resultingParameterName:"knowledgePieces",dependentParameterNames:["knowledgeContent"]}],personas:[],preparations:[],knowledgeSources:[],knowledgePieces:[],sources:[{type:"BOOK",path:null,content:"# Prepare Knowledge from Markdown\n\n- PIPELINE URL `https://promptbook.studio/promptbook/prepare-knowledge-from-markdown.book`\n- INPUT PARAMETER `{knowledgeContent}` Markdown document content\n- OUTPUT PARAMETER `{knowledgePieces}` The knowledge JSON object\n\n## Knowledge\n\n<!-- TODO: [🍆] -FORMAT JSON -->\n\n```markdown\nYou 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}\n```\n\n`-> {knowledgePieces}`\n"}],sourceFile:"./books/prepare-knowledge-from-markdown.book"},{title:"Prepare Keywords",pipelineUrl:"https://promptbook.studio/promptbook/prepare-knowledge-keywords.book",formfactorName:"GENERIC",parameters:[{name:"knowledgePieceContent",description:"The content",isInput:true,isOutput:false},{name:"keywords",description:"Keywords separated by comma",isInput:false,isOutput:true}],tasks:[{taskType:"PROMPT_TASK",name:"knowledge",title:"Knowledge",content:"You are experienced data researcher, detect the important keywords in the document.\n\n# Rules\n\n- Write just keywords separated by comma\n\n# The document\n\nTake information from this document:\n\n> {knowledgePieceContent}",resultingParameterName:"keywords",dependentParameterNames:["knowledgePieceContent"]}],personas:[],preparations:[],knowledgeSources:[],knowledgePieces:[],sources:[{type:"BOOK",path:null,content:"# Prepare Keywords\n\n- PIPELINE URL `https://promptbook.studio/promptbook/prepare-knowledge-keywords.book`\n- INPUT PARAMETER `{knowledgePieceContent}` The content\n- OUTPUT PARAMETER `{keywords}` Keywords separated by comma\n\n## Knowledge\n\n<!-- TODO: [🍆] -FORMAT JSON -->\n\n```markdown\nYou 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}\n```\n\n`-> {keywords}`\n"}],sourceFile:"./books/prepare-knowledge-keywords.book"},{title:"Prepare Knowledge-piece Title",pipelineUrl:"https://promptbook.studio/promptbook/prepare-knowledge-title.book",formfactorName:"GENERIC",parameters:[{name:"knowledgePieceContent",description:"The content",isInput:true,isOutput:false},{name:"title",description:"The title of the document",isInput:false,isOutput:true}],tasks:[{taskType:"PROMPT_TASK",name:"knowledge",title:"Knowledge",content:"You are experienced content creator, write best title for the document.\n\n# Rules\n\n- Write just title, nothing else\n- Write maximum 5 words for the title\n\n# The document\n\n> {knowledgePieceContent}",resultingParameterName:"title",expectations:{words:{min:1,max:8}},dependentParameterNames:["knowledgePieceContent"]}],personas:[],preparations:[],knowledgeSources:[],knowledgePieces:[],sources:[{type:"BOOK",path:null,content:"# Prepare Knowledge-piece Title\n\n- PIPELINE URL `https://promptbook.studio/promptbook/prepare-knowledge-title.book`\n- INPUT PARAMETER `{knowledgePieceContent}` The content\n- OUTPUT PARAMETER `{title}` The title of the document\n\n## Knowledge\n\n- EXPECT MIN 1 WORD\n- EXPECT MAX 8 WORDS\n\n```markdown\nYou are experienced content creator, write best title for the document.\n\n# Rules\n\n- Write just title, nothing else\n- Write maximum 5 words for the title\n\n# The document\n\n> {knowledgePieceContent}\n```\n\n`-> {title}`\n"}],sourceFile:"./books/prepare-knowledge-title.book"},{title:"Prepare Persona",pipelineUrl:"https://promptbook.studio/promptbook/prepare-persona.book",formfactorName:"GENERIC",parameters:[{name:"availableModelNames",description:"List of available model names separated by comma (,)",isInput:true,isOutput:false},{name:"personaDescription",description:"Description of the persona",isInput:true,isOutput:false},{name:"modelRequirements",description:"Specific requirements for the model",isInput:false,isOutput:true}],tasks:[{taskType:"PROMPT_TASK",name:"make-model-requirements",title:"Make modelRequirements",content:"You are experienced AI engineer, you need to create virtual assistant.\nWrite\n\n## Example\n\n```json\n{\n\"modelName\": \"gpt-4o\",\n\"systemMessage\": \"You are experienced AI engineer and helpfull assistant.\",\n\"temperature\": 0.7\n}\n```\n\n## Instructions\n\n- Your output format is JSON object\n- Write just the JSON object, no other text should be present\n- It contains the following keys:\n - `modelName`: The name of the model to use\n - `systemMessage`: The system message to provide context to the model\n - `temperature`: The sampling temperature to use\n\n### Key `modelName`\n\nPick from the following models:\n\n- {availableModelNames}\n\n### Key `systemMessage`\n\nThe system message is used to communicate instructions or provide context to the model at the beginning of a conversation. It is displayed in a different format compared to user messages, helping the model understand its role in the conversation. The system message typically guides the model's behavior, sets the tone, or specifies desired output from the model. By utilizing the system message effectively, users can steer the model towards generating more accurate and relevant responses.\n\nFor example:\n\n> You are an experienced AI engineer and helpful assistant.\n\n> You are a friendly and knowledgeable chatbot.\n\n### Key `temperature`\n\nThe sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, the model will use log probability to automatically increase the temperature until certain thresholds are hit.\n\nYou can pick a value between 0 and 2. For example:\n\n- `0.1`: Low temperature, extremely conservative and deterministic\n- `0.5`: Medium temperature, balanced between conservative and creative\n- `1.0`: High temperature, creative and bit random\n- `1.5`: Very high temperature, extremely creative and often chaotic and unpredictable\n- `2.0`: Maximum temperature, completely random and unpredictable, for some extreme creative use cases\n\n# The assistant\n\nTake this description of the persona:\n\n> {personaDescription}",resultingParameterName:"modelRequirements",format:"JSON",dependentParameterNames:["availableModelNames","personaDescription"]}],personas:[],preparations:[],knowledgeSources:[],knowledgePieces:[],sources:[{type:"BOOK",path:null,content:"# Prepare Persona\n\n- PIPELINE URL `https://promptbook.studio/promptbook/prepare-persona.book`\n- INPUT PARAMETER `{availableModelNames}` List of available model names separated by comma (,)\n- INPUT PARAMETER `{personaDescription}` Description of the persona\n- OUTPUT PARAMETER `{modelRequirements}` Specific requirements for the model\n\n## Make modelRequirements\n\n- FORMAT JSON\n\n```markdown\nYou are experienced AI engineer, you need to create virtual assistant.\nWrite\n\n## Example\n\n\\`\\`\\`json\n{\n\"modelName\": \"gpt-4o\",\n\"systemMessage\": \"You are experienced AI engineer and helpfull assistant.\",\n\"temperature\": 0.7\n}\n\\`\\`\\`\n\n## Instructions\n\n- Your output format is JSON object\n- Write just the JSON object, no other text should be present\n- It contains the following keys:\n - `modelName`: The name of the model to use\n - `systemMessage`: The system message to provide context to the model\n - `temperature`: The sampling temperature to use\n\n### Key `modelName`\n\nPick from the following models:\n\n- {availableModelNames}\n\n### Key `systemMessage`\n\nThe system message is used to communicate instructions or provide context to the model at the beginning of a conversation. It is displayed in a different format compared to user messages, helping the model understand its role in the conversation. The system message typically guides the model's behavior, sets the tone, or specifies desired output from the model. By utilizing the system message effectively, users can steer the model towards generating more accurate and relevant responses.\n\nFor example:\n\n> You are an experienced AI engineer and helpful assistant.\n\n> You are a friendly and knowledgeable chatbot.\n\n### Key `temperature`\n\nThe sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, the model will use log probability to automatically increase the temperature until certain thresholds are hit.\n\nYou can pick a value between 0 and 2. For example:\n\n- `0.1`: Low temperature, extremely conservative and deterministic\n- `0.5`: Medium temperature, balanced between conservative and creative\n- `1.0`: High temperature, creative and bit random\n- `1.5`: Very high temperature, extremely creative and often chaotic and unpredictable\n- `2.0`: Maximum temperature, completely random and unpredictable, for some extreme creative use cases\n\n# The assistant\n\nTake this description of the persona:\n\n> {personaDescription}\n```\n\n`-> {modelRequirements}`\n"}],sourceFile:"./books/prepare-persona.book"},{title:"Prepare Title",pipelineUrl:"https://promptbook.studio/promptbook/prepare-title.book",formfactorName:"GENERIC",parameters:[{name:"book",description:"The book to prepare the title for",isInput:true,isOutput:false},{name:"title",description:"Best title for the book",isInput:false,isOutput:true}],tasks:[{taskType:"PROMPT_TASK",name:"make-title",title:"Make title",content:"Make best title for given text which describes the workflow:\n\n## Rules\n\n- Write just title, nothing else\n- Title should be concise and clear - Write maximum ideally 2 words, maximum 5 words\n- Title starts with emoticon\n- Title should not mention the input and output of the workflow but the main purpose of the workflow\n _For example, not \"✍ Convert Knowledge-piece to title\" but \"✍ Title\"_\n\n## The workflow\n\n> {book}",resultingParameterName:"title",expectations:{words:{min:1,max:8},lines:{min:1,max:1}},dependentParameterNames:["book"]}],personas:[],preparations:[],knowledgeSources:[],knowledgePieces:[],sources:[{type:"BOOK",path:null,content:"# Prepare Title\n\n- PIPELINE URL `https://promptbook.studio/promptbook/prepare-title.book`\n- INPUT PARAMETER `{book}` The book to prepare the title for\n- OUTPUT PARAMETER `{title}` Best title for the book\n\n## Make title\n\n- EXPECT MIN 1 Word\n- EXPECT MAX 8 Words\n- EXPECT EXACTLY 1 Line\n\n```markdown\nMake best title for given text which describes the workflow:\n\n## Rules\n\n- Write just title, nothing else\n- Title should be concise and clear - Write maximum ideally 2 words, maximum 5 words\n- Title starts with emoticon\n- Title should not mention the input and output of the workflow but the main purpose of the workflow\n _For example, not \"✍ Convert Knowledge-piece to title\" but \"✍ Title\"_\n\n## The workflow\n\n> {book}\n```\n\n`-> {title}`\n"}],sourceFile:"./books/prepare-title.book"}];
|
|
4027
4125
|
|
|
4028
4126
|
/**
|
|
4029
|
-
*
|
|
4030
|
-
*
|
|
4031
|
-
* Note: There are two simmilar functions:
|
|
4032
|
-
* - `isValidSemanticVersion` which tests any semantic version
|
|
4033
|
-
* - `isValidPromptbookVersion` *(this one)* which tests just Promptbook versions
|
|
4127
|
+
* Checks if value is valid email
|
|
4034
4128
|
*
|
|
4035
4129
|
* @public exported from `@promptbook/utils`
|
|
4036
4130
|
*/
|
|
4037
|
-
function
|
|
4038
|
-
if (typeof
|
|
4131
|
+
function isValidEmail(email) {
|
|
4132
|
+
if (typeof email !== 'string') {
|
|
4039
4133
|
return false;
|
|
4040
4134
|
}
|
|
4041
|
-
if (
|
|
4135
|
+
if (email.split('\n').length > 1) {
|
|
4042
4136
|
return false;
|
|
4043
4137
|
}
|
|
4044
|
-
return
|
|
4138
|
+
return /^.+@.+\..+$/.test(email);
|
|
4045
4139
|
}
|
|
4046
4140
|
|
|
4047
4141
|
/**
|
|
4048
|
-
*
|
|
4049
|
-
* It looks into list of known promptbook versions.
|
|
4050
|
-
*
|
|
4051
|
-
* @see https://www.npmjs.com/package/promptbook?activeTab=versions
|
|
4052
|
-
* 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.
|
|
4053
|
-
* Note: There are two simmilar functions:
|
|
4054
|
-
* - `isValidSemanticVersion` which tests any semantic version
|
|
4055
|
-
* - `isValidPromptbookVersion` *(this one)* which tests just Promptbook versions
|
|
4142
|
+
* Function isValidJsonString will tell you if the string is valid JSON or not
|
|
4056
4143
|
*
|
|
4057
4144
|
* @public exported from `@promptbook/utils`
|
|
4058
4145
|
*/
|
|
4059
|
-
function
|
|
4060
|
-
|
|
4061
|
-
|
|
4146
|
+
function isValidJsonString(value /* <- [👨⚖️] */) {
|
|
4147
|
+
try {
|
|
4148
|
+
JSON.parse(value);
|
|
4149
|
+
return true;
|
|
4062
4150
|
}
|
|
4063
|
-
|
|
4151
|
+
catch (error) {
|
|
4152
|
+
if (!(error instanceof Error)) {
|
|
4153
|
+
throw error;
|
|
4154
|
+
}
|
|
4155
|
+
if (error.message.includes('Unexpected token')) {
|
|
4156
|
+
return false;
|
|
4157
|
+
}
|
|
4064
4158
|
return false;
|
|
4065
4159
|
}
|
|
4066
|
-
// <- TODO: [main] !!3 Check isValidPromptbookVersion against PROMPTBOOK_ENGINE_VERSIONS
|
|
4067
|
-
return true;
|
|
4068
4160
|
}
|
|
4069
4161
|
|
|
4070
4162
|
/**
|
|
4071
|
-
*
|
|
4072
|
-
*
|
|
4073
|
-
* Note: There are two simmilar functions:
|
|
4074
|
-
* - `isValidUrl` which tests any URL
|
|
4075
|
-
* - `isValidPipelineUrl` *(this one)* which tests just pipeline URL
|
|
4163
|
+
* Function `validatePipelineString` will validate the if the string is a valid pipeline string
|
|
4164
|
+
* It does not check if the string is fully logically correct, but if it is a string that can be a pipeline string or the string looks completely different.
|
|
4076
4165
|
*
|
|
4077
|
-
* @
|
|
4166
|
+
* @param {string} pipelineString the candidate for a pipeline string
|
|
4167
|
+
* @returns {PipelineString} the same string as input, but validated as valid
|
|
4168
|
+
* @throws {ParseError} if the string is not a valid pipeline string
|
|
4169
|
+
* @public exported from `@promptbook/core`
|
|
4078
4170
|
*/
|
|
4079
|
-
function
|
|
4080
|
-
if (
|
|
4081
|
-
|
|
4171
|
+
function validatePipelineString(pipelineString) {
|
|
4172
|
+
if (isValidJsonString(pipelineString)) {
|
|
4173
|
+
throw new ParseError('Expected a book, but got a JSON string');
|
|
4082
4174
|
}
|
|
4083
|
-
if (
|
|
4084
|
-
|
|
4175
|
+
else if (isValidUrl(pipelineString)) {
|
|
4176
|
+
throw new ParseError("Expected a book, but got just the URL \"".concat(pipelineString, "\""));
|
|
4085
4177
|
}
|
|
4086
|
-
if (
|
|
4087
|
-
|
|
4088
|
-
return false;
|
|
4178
|
+
else if (isValidFilePath(pipelineString)) {
|
|
4179
|
+
throw new ParseError("Expected a book, but got just the file path \"".concat(pipelineString, "\""));
|
|
4089
4180
|
}
|
|
4090
|
-
|
|
4091
|
-
|
|
4092
|
-
if (isUrlOnPrivateNetwork(url)) {
|
|
4093
|
-
return false;
|
|
4181
|
+
else if (isValidEmail(pipelineString)) {
|
|
4182
|
+
throw new ParseError("Expected a book, but got just the email \"".concat(pipelineString, "\""));
|
|
4094
4183
|
}
|
|
4095
|
-
|
|
4096
|
-
return
|
|
4184
|
+
// <- TODO: Implement the validation + add tests when the pipeline logic considered as invalid
|
|
4185
|
+
return pipelineString;
|
|
4097
4186
|
}
|
|
4098
4187
|
/**
|
|
4099
|
-
* TODO: [
|
|
4188
|
+
* TODO: [🧠][🈴] Where is the best location for this file
|
|
4100
4189
|
*/
|
|
4101
4190
|
|
|
4102
4191
|
/**
|
|
4103
|
-
*
|
|
4104
|
-
*
|
|
4105
|
-
* It checks:
|
|
4106
|
-
* - if it has correct parameters dependency
|
|
4107
|
-
*
|
|
4108
|
-
* It does NOT check:
|
|
4109
|
-
* - if it is valid json
|
|
4110
|
-
* - if it is meaningful
|
|
4192
|
+
* Prettify the html code
|
|
4111
4193
|
*
|
|
4112
|
-
* @param
|
|
4113
|
-
* @returns
|
|
4114
|
-
* @
|
|
4115
|
-
* @public exported from `@promptbook/core`
|
|
4194
|
+
* @param content raw html code
|
|
4195
|
+
* @returns formatted html code
|
|
4196
|
+
* @private withing the package because of HUGE size of prettier dependency
|
|
4116
4197
|
*/
|
|
4117
|
-
function
|
|
4118
|
-
|
|
4119
|
-
|
|
4198
|
+
function prettifyMarkdown(content) {
|
|
4199
|
+
try {
|
|
4200
|
+
return format(content, {
|
|
4201
|
+
parser: 'markdown',
|
|
4202
|
+
plugins: [parserHtml],
|
|
4203
|
+
// TODO: DRY - make some import or auto-copy of .prettierrc
|
|
4204
|
+
endOfLine: 'lf',
|
|
4205
|
+
tabWidth: 4,
|
|
4206
|
+
singleQuote: true,
|
|
4207
|
+
trailingComma: 'all',
|
|
4208
|
+
arrowParens: 'always',
|
|
4209
|
+
printWidth: 120,
|
|
4210
|
+
htmlWhitespaceSensitivity: 'ignore',
|
|
4211
|
+
jsxBracketSameLine: false,
|
|
4212
|
+
bracketSpacing: true,
|
|
4213
|
+
});
|
|
4120
4214
|
}
|
|
4121
|
-
|
|
4122
|
-
|
|
4123
|
-
|
|
4124
|
-
|
|
4125
|
-
|
|
4126
|
-
|
|
4127
|
-
|
|
4128
|
-
}
|
|
4129
|
-
console.error(spaceTrim$1(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 "); }));
|
|
4130
|
-
}
|
|
4215
|
+
catch (error) {
|
|
4216
|
+
// TODO: [🟥] Detect browser / node and make it colorfull
|
|
4217
|
+
console.error('There was an error with prettifying the markdown, using the original as the fallback', {
|
|
4218
|
+
error: error,
|
|
4219
|
+
html: content,
|
|
4220
|
+
});
|
|
4221
|
+
return content;
|
|
4131
4222
|
}
|
|
4132
|
-
return pipeline;
|
|
4133
4223
|
}
|
|
4224
|
+
|
|
4134
4225
|
/**
|
|
4135
|
-
*
|
|
4226
|
+
* Makes first letter of a string uppercase
|
|
4227
|
+
*
|
|
4228
|
+
* @public exported from `@promptbook/utils`
|
|
4136
4229
|
*/
|
|
4137
|
-
function
|
|
4138
|
-
|
|
4139
|
-
|
|
4140
|
-
|
|
4141
|
-
|
|
4142
|
-
|
|
4143
|
-
|
|
4144
|
-
|
|
4145
|
-
|
|
4146
|
-
|
|
4147
|
-
|
|
4148
|
-
|
|
4149
|
-
|
|
4150
|
-
|
|
4151
|
-
|
|
4152
|
-
|
|
4153
|
-
|
|
4154
|
-
|
|
4155
|
-
|
|
4156
|
-
// <- Note: [🚲]
|
|
4157
|
-
throw new PipelineLogicError(spaceTrim$1(function (block) { return "\n Invalid Promptbook Version \"".concat(pipeline.bookVersion, "\"\n\n ").concat(block(pipelineIdentification), "\n "); }));
|
|
4230
|
+
function capitalize(word) {
|
|
4231
|
+
return word.substring(0, 1).toUpperCase() + word.substring(1);
|
|
4232
|
+
}
|
|
4233
|
+
|
|
4234
|
+
/**
|
|
4235
|
+
* Converts promptbook in JSON format to string format
|
|
4236
|
+
*
|
|
4237
|
+
* @deprecated TODO: [🥍][🧠] Backup original files in `PipelineJson` same as in Promptbook.studio
|
|
4238
|
+
* @param pipelineJson Promptbook in JSON format (.bookc)
|
|
4239
|
+
* @returns Promptbook in string format (.book.md)
|
|
4240
|
+
* @public exported from `@promptbook/core`
|
|
4241
|
+
*/
|
|
4242
|
+
function pipelineJsonToString(pipelineJson) {
|
|
4243
|
+
var e_1, _a, e_2, _b, e_3, _c, e_4, _d, e_5, _e, e_6, _f;
|
|
4244
|
+
var title = pipelineJson.title, pipelineUrl = pipelineJson.pipelineUrl, bookVersion = pipelineJson.bookVersion, description = pipelineJson.description, parameters = pipelineJson.parameters, tasks = pipelineJson.tasks;
|
|
4245
|
+
var pipelineString = "# ".concat(title);
|
|
4246
|
+
if (description) {
|
|
4247
|
+
pipelineString += '\n\n';
|
|
4248
|
+
pipelineString += description;
|
|
4158
4249
|
}
|
|
4159
|
-
|
|
4160
|
-
if (
|
|
4161
|
-
|
|
4162
|
-
throw new ParseError(spaceTrim$1(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 "); }));
|
|
4250
|
+
var commands = [];
|
|
4251
|
+
if (pipelineUrl) {
|
|
4252
|
+
commands.push("PIPELINE URL ".concat(pipelineUrl));
|
|
4163
4253
|
}
|
|
4164
|
-
|
|
4165
|
-
|
|
4166
|
-
// TODO: [🧠] what is the correct error tp throw - maybe PromptbookSchemaError
|
|
4167
|
-
throw new ParseError(spaceTrim$1(function (block) { return "\n Pipeline is valid JSON but with wrong structure\n\n `PipelineJson.tasks` expected to be an array, but got ".concat(typeof pipeline.tasks, "\n\n ").concat(block(pipelineIdentification), "\n "); }));
|
|
4254
|
+
if (bookVersion !== "undefined") {
|
|
4255
|
+
commands.push("BOOK VERSION ".concat(bookVersion));
|
|
4168
4256
|
}
|
|
4169
|
-
|
|
4170
|
-
|
|
4171
|
-
throw new PipelineLogicError(spaceTrim$1(function (block) { return "\n\n Parameter `{".concat(parameter.name, "}` can not be both input and output\n\n ").concat(block(pipelineIdentification), "\n "); }));
|
|
4172
|
-
}
|
|
4173
|
-
// Note: Testing that parameter is either intermediate or output BUT not created and unused
|
|
4174
|
-
if (!parameter.isInput &&
|
|
4175
|
-
!parameter.isOutput &&
|
|
4176
|
-
!pipeline.tasks.some(function (task) { return task.dependentParameterNames.includes(parameter.name); })) {
|
|
4177
|
-
throw new PipelineLogicError(spaceTrim$1(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 "); }));
|
|
4178
|
-
}
|
|
4179
|
-
// Note: Testing that parameter is either input or result of some task
|
|
4180
|
-
if (!parameter.isInput && !pipeline.tasks.some(function (task) { return task.resultingParameterName === parameter.name; })) {
|
|
4181
|
-
throw new PipelineLogicError(spaceTrim$1(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 task that results in `-> {").concat(parameter.name, "}`\n\n ").concat(block(pipelineIdentification), "\n "); }));
|
|
4182
|
-
}
|
|
4183
|
-
};
|
|
4257
|
+
// TODO: [main] !!5 This increases size of the bundle and is probbably not necessary
|
|
4258
|
+
pipelineString = prettifyMarkdown(pipelineString);
|
|
4184
4259
|
try {
|
|
4185
|
-
|
|
4186
|
-
|
|
4187
|
-
|
|
4188
|
-
|
|
4189
|
-
|
|
4190
|
-
|
|
4191
|
-
(block) => `
|
|
4192
|
-
Pipeline must have at least one task
|
|
4193
|
-
|
|
4194
|
-
${block(pipelineIdentification)}
|
|
4195
|
-
`,
|
|
4196
|
-
),
|
|
4197
|
-
);
|
|
4198
|
-
}
|
|
4199
|
-
*/
|
|
4200
|
-
// Note: Check each parameter individually
|
|
4201
|
-
for (var _d = __values(pipeline.parameters), _e = _d.next(); !_e.done; _e = _d.next()) {
|
|
4202
|
-
var parameter = _e.value;
|
|
4203
|
-
_loop_1(parameter);
|
|
4260
|
+
for (var _g = __values(parameters.filter(function (_a) {
|
|
4261
|
+
var isInput = _a.isInput;
|
|
4262
|
+
return isInput;
|
|
4263
|
+
})), _h = _g.next(); !_h.done; _h = _g.next()) {
|
|
4264
|
+
var parameter = _h.value;
|
|
4265
|
+
commands.push("INPUT PARAMETER ".concat(taskParameterJsonToString(parameter)));
|
|
4204
4266
|
}
|
|
4205
4267
|
}
|
|
4206
4268
|
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
4207
4269
|
finally {
|
|
4208
4270
|
try {
|
|
4209
|
-
if (
|
|
4271
|
+
if (_h && !_h.done && (_a = _g.return)) _a.call(_g);
|
|
4210
4272
|
}
|
|
4211
4273
|
finally { if (e_1) throw e_1.error; }
|
|
4212
4274
|
}
|
|
4213
|
-
|
|
4214
|
-
|
|
4215
|
-
|
|
4216
|
-
|
|
4217
|
-
|
|
4218
|
-
|
|
4219
|
-
|
|
4220
|
-
}));
|
|
4221
|
-
var _loop_2 = function (task) {
|
|
4222
|
-
var e_4, _h, e_5, _j;
|
|
4223
|
-
if (definedParameters.has(task.resultingParameterName)) {
|
|
4224
|
-
throw new PipelineLogicError(spaceTrim$1(function (block) { return "\n Parameter `{".concat(task.resultingParameterName, "}` is defined multiple times\n\n ").concat(block(pipelineIdentification), "\n "); }));
|
|
4275
|
+
try {
|
|
4276
|
+
for (var _j = __values(parameters.filter(function (_a) {
|
|
4277
|
+
var isOutput = _a.isOutput;
|
|
4278
|
+
return isOutput;
|
|
4279
|
+
})), _k = _j.next(); !_k.done; _k = _j.next()) {
|
|
4280
|
+
var parameter = _k.value;
|
|
4281
|
+
commands.push("OUTPUT PARAMETER ".concat(taskParameterJsonToString(parameter)));
|
|
4225
4282
|
}
|
|
4226
|
-
|
|
4227
|
-
|
|
4283
|
+
}
|
|
4284
|
+
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
4285
|
+
finally {
|
|
4286
|
+
try {
|
|
4287
|
+
if (_k && !_k.done && (_b = _j.return)) _b.call(_j);
|
|
4228
4288
|
}
|
|
4229
|
-
|
|
4230
|
-
|
|
4231
|
-
|
|
4232
|
-
|
|
4233
|
-
|
|
4289
|
+
finally { if (e_2) throw e_2.error; }
|
|
4290
|
+
}
|
|
4291
|
+
pipelineString += '\n\n';
|
|
4292
|
+
pipelineString += commands.map(function (command) { return "- ".concat(command); }).join('\n');
|
|
4293
|
+
try {
|
|
4294
|
+
for (var tasks_1 = __values(tasks), tasks_1_1 = tasks_1.next(); !tasks_1_1.done; tasks_1_1 = tasks_1.next()) {
|
|
4295
|
+
var task = tasks_1_1.value;
|
|
4296
|
+
var
|
|
4297
|
+
/* Note: Not using:> name, */
|
|
4298
|
+
title_1 = task.title, description_1 = task.description,
|
|
4299
|
+
/* Note: dependentParameterNames, */
|
|
4300
|
+
jokers = task.jokerParameterNames, taskType = task.taskType, content = task.content, postprocessing = task.postprocessingFunctionNames, expectations = task.expectations, format = task.format, resultingParameterName = task.resultingParameterName;
|
|
4301
|
+
pipelineString += '\n\n';
|
|
4302
|
+
pipelineString += "## ".concat(title_1);
|
|
4303
|
+
if (description_1) {
|
|
4304
|
+
pipelineString += '\n\n';
|
|
4305
|
+
pipelineString += description_1;
|
|
4234
4306
|
}
|
|
4235
|
-
var
|
|
4236
|
-
|
|
4237
|
-
|
|
4307
|
+
var commands_1 = [];
|
|
4308
|
+
var contentLanguage = 'text';
|
|
4309
|
+
if (taskType === 'PROMPT_TASK') {
|
|
4310
|
+
var modelRequirements = task.modelRequirements;
|
|
4311
|
+
var _l = modelRequirements || {}, modelName = _l.modelName, modelVariant = _l.modelVariant;
|
|
4312
|
+
// Note: Do nothing, it is default
|
|
4313
|
+
// commands.push(`PROMPT`);
|
|
4314
|
+
if (modelVariant) {
|
|
4315
|
+
commands_1.push("MODEL VARIANT ".concat(capitalize(modelVariant)));
|
|
4238
4316
|
}
|
|
4239
|
-
|
|
4240
|
-
|
|
4241
|
-
for (var _k = (e_4 = void 0, __values(task.jokerParameterNames)), _l = _k.next(); !_l.done; _l = _k.next()) {
|
|
4242
|
-
var joker = _l.value;
|
|
4243
|
-
_loop_4(joker);
|
|
4317
|
+
if (modelName) {
|
|
4318
|
+
commands_1.push("MODEL NAME `".concat(modelName, "`"));
|
|
4244
4319
|
}
|
|
4245
4320
|
}
|
|
4246
|
-
|
|
4247
|
-
|
|
4248
|
-
|
|
4249
|
-
|
|
4321
|
+
else if (taskType === 'SIMPLE_TASK') {
|
|
4322
|
+
commands_1.push("SIMPLE TEMPLATE");
|
|
4323
|
+
// Note: Nothing special here
|
|
4324
|
+
}
|
|
4325
|
+
else if (taskType === 'SCRIPT_TASK') {
|
|
4326
|
+
commands_1.push("SCRIPT");
|
|
4327
|
+
if (task.contentLanguage) {
|
|
4328
|
+
contentLanguage = task.contentLanguage;
|
|
4329
|
+
}
|
|
4330
|
+
else {
|
|
4331
|
+
contentLanguage = '';
|
|
4250
4332
|
}
|
|
4251
|
-
finally { if (e_4) throw e_4.error; }
|
|
4252
4333
|
}
|
|
4253
|
-
|
|
4254
|
-
|
|
4255
|
-
|
|
4256
|
-
|
|
4257
|
-
|
|
4334
|
+
else if (taskType === 'DIALOG_TASK') {
|
|
4335
|
+
commands_1.push("DIALOG");
|
|
4336
|
+
// Note: Nothing special here
|
|
4337
|
+
} // <- }else if([🅱]
|
|
4338
|
+
if (jokers) {
|
|
4339
|
+
try {
|
|
4340
|
+
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()) {
|
|
4341
|
+
var joker = jokers_1_1.value;
|
|
4342
|
+
commands_1.push("JOKER {".concat(joker, "}"));
|
|
4343
|
+
}
|
|
4258
4344
|
}
|
|
4259
|
-
|
|
4260
|
-
|
|
4345
|
+
catch (e_4_1) { e_4 = { error: e_4_1 }; }
|
|
4346
|
+
finally {
|
|
4347
|
+
try {
|
|
4348
|
+
if (jokers_1_1 && !jokers_1_1.done && (_d = jokers_1.return)) _d.call(jokers_1);
|
|
4349
|
+
}
|
|
4350
|
+
finally { if (e_4) throw e_4.error; }
|
|
4261
4351
|
}
|
|
4262
|
-
|
|
4263
|
-
|
|
4352
|
+
} /* not else */
|
|
4353
|
+
if (postprocessing) {
|
|
4354
|
+
try {
|
|
4355
|
+
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()) {
|
|
4356
|
+
var postprocessingFunctionName = postprocessing_1_1.value;
|
|
4357
|
+
commands_1.push("POSTPROCESSING `".concat(postprocessingFunctionName, "`"));
|
|
4358
|
+
}
|
|
4359
|
+
}
|
|
4360
|
+
catch (e_5_1) { e_5 = { error: e_5_1 }; }
|
|
4361
|
+
finally {
|
|
4362
|
+
try {
|
|
4363
|
+
if (postprocessing_1_1 && !postprocessing_1_1.done && (_e = postprocessing_1.return)) _e.call(postprocessing_1);
|
|
4364
|
+
}
|
|
4365
|
+
finally { if (e_5) throw e_5.error; }
|
|
4366
|
+
}
|
|
4367
|
+
} /* not else */
|
|
4368
|
+
if (expectations) {
|
|
4369
|
+
try {
|
|
4370
|
+
for (var _m = (e_6 = void 0, __values(Object.entries(expectations))), _o = _m.next(); !_o.done; _o = _m.next()) {
|
|
4371
|
+
var _p = __read(_o.value, 2), unit = _p[0], _q = _p[1], min = _q.min, max = _q.max;
|
|
4372
|
+
if (min === max) {
|
|
4373
|
+
commands_1.push("EXPECT EXACTLY ".concat(min, " ").concat(capitalize(unit + (min > 1 ? 's' : ''))));
|
|
4374
|
+
}
|
|
4375
|
+
else {
|
|
4376
|
+
if (min !== undefined) {
|
|
4377
|
+
commands_1.push("EXPECT MIN ".concat(min, " ").concat(capitalize(unit + (min > 1 ? 's' : ''))));
|
|
4378
|
+
} /* not else */
|
|
4379
|
+
if (max !== undefined) {
|
|
4380
|
+
commands_1.push("EXPECT MAX ".concat(max, " ").concat(capitalize(unit + (max > 1 ? 's' : ''))));
|
|
4381
|
+
}
|
|
4382
|
+
}
|
|
4383
|
+
}
|
|
4264
4384
|
}
|
|
4265
|
-
|
|
4266
|
-
|
|
4267
|
-
|
|
4268
|
-
|
|
4269
|
-
|
|
4385
|
+
catch (e_6_1) { e_6 = { error: e_6_1 }; }
|
|
4386
|
+
finally {
|
|
4387
|
+
try {
|
|
4388
|
+
if (_o && !_o.done && (_f = _m.return)) _f.call(_m);
|
|
4389
|
+
}
|
|
4390
|
+
finally { if (e_6) throw e_6.error; }
|
|
4270
4391
|
}
|
|
4271
|
-
}
|
|
4272
|
-
|
|
4273
|
-
|
|
4274
|
-
|
|
4275
|
-
|
|
4392
|
+
} /* not else */
|
|
4393
|
+
if (format) {
|
|
4394
|
+
if (format === 'JSON') {
|
|
4395
|
+
// TODO: @deprecated remove
|
|
4396
|
+
commands_1.push("FORMAT JSON");
|
|
4276
4397
|
}
|
|
4277
|
-
|
|
4278
|
-
|
|
4279
|
-
|
|
4280
|
-
|
|
4281
|
-
|
|
4282
|
-
|
|
4283
|
-
|
|
4284
|
-
|
|
4285
|
-
|
|
4286
|
-
|
|
4287
|
-
|
|
4288
|
-
|
|
4289
|
-
|
|
4290
|
-
try {
|
|
4291
|
-
if (_g && !_g.done && (_b = _f.return)) _b.call(_f);
|
|
4292
|
-
}
|
|
4293
|
-
finally { if (e_2) throw e_2.error; }
|
|
4294
|
-
}
|
|
4295
|
-
// Note: Detect circular dependencies
|
|
4296
|
-
var resovedParameters = pipeline.parameters
|
|
4297
|
-
.filter(function (_a) {
|
|
4298
|
-
var isInput = _a.isInput;
|
|
4299
|
-
return isInput;
|
|
4300
|
-
})
|
|
4301
|
-
.map(function (_a) {
|
|
4302
|
-
var name = _a.name;
|
|
4303
|
-
return name;
|
|
4304
|
-
});
|
|
4305
|
-
try {
|
|
4306
|
-
// Note: All reserved parameters are resolved
|
|
4307
|
-
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()) {
|
|
4308
|
-
var reservedParameterName = RESERVED_PARAMETER_NAMES_1_1.value;
|
|
4309
|
-
resovedParameters = __spreadArray(__spreadArray([], __read(resovedParameters), false), [reservedParameterName], false);
|
|
4398
|
+
} /* not else */
|
|
4399
|
+
pipelineString += '\n\n';
|
|
4400
|
+
pipelineString += commands_1.map(function (command) { return "- ".concat(command); }).join('\n');
|
|
4401
|
+
pipelineString += '\n\n';
|
|
4402
|
+
pipelineString += '```' + contentLanguage;
|
|
4403
|
+
pipelineString += '\n';
|
|
4404
|
+
pipelineString += spaceTrim(content);
|
|
4405
|
+
// <- TODO: [main] !!3 Escape
|
|
4406
|
+
// <- TODO: [🧠] Some clear strategy how to spaceTrim the blocks
|
|
4407
|
+
pipelineString += '\n';
|
|
4408
|
+
pipelineString += '```';
|
|
4409
|
+
pipelineString += '\n\n';
|
|
4410
|
+
pipelineString += "`-> {".concat(resultingParameterName, "}`"); // <- TODO: [main] !!3 If the parameter here has description, add it and use taskParameterJsonToString
|
|
4310
4411
|
}
|
|
4311
4412
|
}
|
|
4312
4413
|
catch (e_3_1) { e_3 = { error: e_3_1 }; }
|
|
4313
4414
|
finally {
|
|
4314
4415
|
try {
|
|
4315
|
-
if (
|
|
4416
|
+
if (tasks_1_1 && !tasks_1_1.done && (_c = tasks_1.return)) _c.call(tasks_1);
|
|
4316
4417
|
}
|
|
4317
4418
|
finally { if (e_3) throw e_3.error; }
|
|
4318
4419
|
}
|
|
4319
|
-
|
|
4320
|
-
var loopLimit = LOOP_LIMIT;
|
|
4321
|
-
var _loop_3 = function () {
|
|
4322
|
-
if (loopLimit-- < 0) {
|
|
4323
|
-
// Note: Really UnexpectedError not LimitReachedError - this should not happen and be caught below
|
|
4324
|
-
throw new UnexpectedError(spaceTrim$1(function (block) { return "\n Loop limit reached during detection of circular dependencies in `validatePipeline`\n\n ".concat(block(pipelineIdentification), "\n "); }));
|
|
4325
|
-
}
|
|
4326
|
-
var currentlyResovedTasks = unresovedTasks.filter(function (task) {
|
|
4327
|
-
return task.dependentParameterNames.every(function (name) { return resovedParameters.includes(name); });
|
|
4328
|
-
});
|
|
4329
|
-
if (currentlyResovedTasks.length === 0) {
|
|
4330
|
-
throw new PipelineLogicError(
|
|
4331
|
-
// TODO: [🐎] DRY
|
|
4332
|
-
spaceTrim$1(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(unresovedTasks
|
|
4333
|
-
.map(function (_a) {
|
|
4334
|
-
var resultingParameterName = _a.resultingParameterName, dependentParameterNames = _a.dependentParameterNames;
|
|
4335
|
-
return "- Parameter `{".concat(resultingParameterName, "}` which depends on ").concat(dependentParameterNames
|
|
4336
|
-
.map(function (dependentParameterName) { return "`{".concat(dependentParameterName, "}`"); })
|
|
4337
|
-
.join(' and '));
|
|
4338
|
-
})
|
|
4339
|
-
.join('\n')), "\n\n **Resolved:**\n ").concat(block(resovedParameters
|
|
4340
|
-
.filter(function (name) {
|
|
4341
|
-
return !RESERVED_PARAMETER_NAMES.includes(name);
|
|
4342
|
-
})
|
|
4343
|
-
.map(function (name) { return "- Parameter `{".concat(name, "}`"); })
|
|
4344
|
-
.join('\n')), "\n\n\n **Reserved (which are available):**\n ").concat(block(resovedParameters
|
|
4345
|
-
.filter(function (name) {
|
|
4346
|
-
return RESERVED_PARAMETER_NAMES.includes(name);
|
|
4347
|
-
})
|
|
4348
|
-
.map(function (name) { return "- Parameter `{".concat(name, "}`"); })
|
|
4349
|
-
.join('\n')), "\n\n\n "); }));
|
|
4350
|
-
}
|
|
4351
|
-
resovedParameters = __spreadArray(__spreadArray([], __read(resovedParameters), false), __read(currentlyResovedTasks.map(function (_a) {
|
|
4352
|
-
var resultingParameterName = _a.resultingParameterName;
|
|
4353
|
-
return resultingParameterName;
|
|
4354
|
-
})), false);
|
|
4355
|
-
unresovedTasks = unresovedTasks.filter(function (task) { return !currentlyResovedTasks.includes(task); });
|
|
4356
|
-
};
|
|
4357
|
-
while (unresovedTasks.length > 0) {
|
|
4358
|
-
_loop_3();
|
|
4359
|
-
}
|
|
4360
|
-
// Note: Check that formfactor is corresponding to the pipeline interface
|
|
4361
|
-
// TODO: !!6 Implement this
|
|
4362
|
-
// pipeline.formfactorName
|
|
4420
|
+
return validatePipelineString(pipelineString);
|
|
4363
4421
|
}
|
|
4364
4422
|
/**
|
|
4365
|
-
*
|
|
4366
|
-
* TODO: [🧠] Work with promptbookVersion
|
|
4367
|
-
* TODO: Use here some json-schema, Zod or something similar and change it to:
|
|
4368
|
-
* > /**
|
|
4369
|
-
* > * Validates PipelineJson if it is logically valid.
|
|
4370
|
-
* > *
|
|
4371
|
-
* > * It checks:
|
|
4372
|
-
* > * - it has a valid structure
|
|
4373
|
-
* > * - ...
|
|
4374
|
-
* > ex port function validatePipeline(promptbook: really_unknown): asserts promptbook is PipelineJson {
|
|
4423
|
+
* @private internal utility of `pipelineJsonToString`
|
|
4375
4424
|
*/
|
|
4425
|
+
function taskParameterJsonToString(taskParameterJson) {
|
|
4426
|
+
var name = taskParameterJson.name, description = taskParameterJson.description;
|
|
4427
|
+
var parameterString = "{".concat(name, "}");
|
|
4428
|
+
if (description) {
|
|
4429
|
+
parameterString = "".concat(parameterString, " ").concat(description);
|
|
4430
|
+
}
|
|
4431
|
+
return parameterString;
|
|
4432
|
+
}
|
|
4376
4433
|
/**
|
|
4377
|
-
* TODO: [
|
|
4378
|
-
* TODO: [
|
|
4379
|
-
* TODO: [
|
|
4380
|
-
* TODO: [
|
|
4381
|
-
* TODO: [
|
|
4382
|
-
* TODO: [🧠] Validation not only logic itself but imports around - files and websites and rerefenced pipelines exists
|
|
4383
|
-
* TODO: [🛠] Actions, instruments (and maybe knowledge) => Functions and tools
|
|
4434
|
+
* TODO: [🛋] Implement new features and commands into `pipelineJsonToString` + `taskParameterJsonToString` , use `stringifyCommand`
|
|
4435
|
+
* TODO: [🧠] Is there a way to auto-detect missing features in pipelineJsonToString
|
|
4436
|
+
* TODO: [🏛] Maybe make some markdown builder
|
|
4437
|
+
* TODO: [🏛] Escape all
|
|
4438
|
+
* TODO: [🧠] Should be in generated .book.md file GENERATOR_WARNING
|
|
4384
4439
|
*/
|
|
4385
4440
|
|
|
4386
4441
|
/**
|
|
@@ -12027,17 +12082,17 @@ function createCollectionFromDirectory(rootPath, tools, options) {
|
|
|
12027
12082
|
}
|
|
12028
12083
|
_a = options || {}, _b = _a.isRecursive, isRecursive = _b === void 0 ? true : _b, _c = _a.isVerbose, isVerbose = _c === void 0 ? DEFAULT_IS_VERBOSE : _c, _d = _a.isLazyLoaded, isLazyLoaded = _d === void 0 ? false : _d, _e = _a.isCrashedOnError, isCrashedOnError = _e === void 0 ? true : _e, rootUrl = _a.rootUrl;
|
|
12029
12084
|
collection = createCollectionFromPromise(function () { return __awaiter(_this, void 0, void 0, function () {
|
|
12030
|
-
var fileNames, collection, _loop_1, fileNames_1, fileNames_1_1, fileName, e_1_1;
|
|
12031
|
-
var e_1, _a;
|
|
12032
|
-
return __generator(this, function (
|
|
12033
|
-
switch (
|
|
12085
|
+
var fileNames, collection, pipelinesWithFilenames, _loop_1, fileNames_1, fileNames_1_1, fileName, e_1_1, _loop_2, pipelinesWithFilenames_1, pipelinesWithFilenames_1_1, pipelineWithFilenames;
|
|
12086
|
+
var e_1, _a, e_2, _b;
|
|
12087
|
+
return __generator(this, function (_c) {
|
|
12088
|
+
switch (_c.label) {
|
|
12034
12089
|
case 0:
|
|
12035
12090
|
if (isVerbose) {
|
|
12036
12091
|
console.info(colors.cyan("Creating pipeline collection from path ".concat(rootPath.split('\\').join('/'))));
|
|
12037
12092
|
}
|
|
12038
12093
|
return [4 /*yield*/, listAllFiles(rootPath, isRecursive, tools.fs)];
|
|
12039
12094
|
case 1:
|
|
12040
|
-
fileNames =
|
|
12095
|
+
fileNames = _c.sent();
|
|
12041
12096
|
// Note: First load compiled `.bookc` files and then source `.book` files
|
|
12042
12097
|
// `.bookc` are already compiled and can be used faster
|
|
12043
12098
|
fileNames.sort(function (a, b) {
|
|
@@ -12050,100 +12105,54 @@ function createCollectionFromDirectory(rootPath, tools, options) {
|
|
|
12050
12105
|
return 0;
|
|
12051
12106
|
});
|
|
12052
12107
|
collection = new Map();
|
|
12108
|
+
pipelinesWithFilenames = [];
|
|
12053
12109
|
_loop_1 = function (fileName) {
|
|
12054
|
-
var sourceFile, rootDirname,
|
|
12055
|
-
return __generator(this, function (
|
|
12056
|
-
switch (
|
|
12110
|
+
var sourceFile, rootDirname, pipelineString, _d, pipeline, _e, _f, _g, _h, error_1, wrappedErrorMessage;
|
|
12111
|
+
return __generator(this, function (_j) {
|
|
12112
|
+
switch (_j.label) {
|
|
12057
12113
|
case 0:
|
|
12058
12114
|
sourceFile = './' + fileName.split('\\').join('/');
|
|
12059
12115
|
rootDirname = dirname(sourceFile).split('\\').join('/');
|
|
12060
|
-
|
|
12116
|
+
_j.label = 1;
|
|
12061
12117
|
case 1:
|
|
12062
|
-
|
|
12063
|
-
pipeline = null;
|
|
12118
|
+
_j.trys.push([1, 8, , 9]);
|
|
12064
12119
|
if (!(fileName.endsWith('.book') || fileName.endsWith('.book.md'))) return [3 /*break*/, 4];
|
|
12065
|
-
|
|
12120
|
+
_d = validatePipelineString;
|
|
12066
12121
|
return [4 /*yield*/, readFile(fileName, 'utf-8')];
|
|
12067
12122
|
case 2:
|
|
12068
|
-
pipelineString =
|
|
12123
|
+
pipelineString = _d.apply(void 0, [_j.sent()]);
|
|
12069
12124
|
return [4 /*yield*/, compilePipeline(pipelineString, tools, {
|
|
12070
12125
|
rootDirname: rootDirname,
|
|
12071
12126
|
})];
|
|
12072
12127
|
case 3:
|
|
12073
|
-
pipeline =
|
|
12074
|
-
pipeline
|
|
12128
|
+
pipeline = _j.sent();
|
|
12129
|
+
pipelinesWithFilenames.push({ fileName: fileName, sourceFile: sourceFile, pipeline: __assign(__assign({}, pipeline), { sourceFile: sourceFile }) });
|
|
12075
12130
|
return [3 /*break*/, 7];
|
|
12076
12131
|
case 4:
|
|
12077
12132
|
if (!(fileName.endsWith('.bookc') || fileName.endsWith('.book.json'))) return [3 /*break*/, 6];
|
|
12078
|
-
|
|
12079
|
-
|
|
12133
|
+
_f =
|
|
12134
|
+
// TODO: Handle non-valid JSON files
|
|
12135
|
+
(_e = pipelinesWithFilenames.push).apply;
|
|
12136
|
+
_g = [
|
|
12137
|
+
// TODO: Handle non-valid JSON files
|
|
12138
|
+
pipelinesWithFilenames];
|
|
12139
|
+
_h = [[]];
|
|
12140
|
+
return [4 /*yield*/, loadArchive(fileName, tools.fs)];
|
|
12080
12141
|
case 5:
|
|
12081
12142
|
// TODO: Handle non-valid JSON files
|
|
12082
|
-
|
|
12083
|
-
|
|
12084
|
-
|
|
12143
|
+
_f.apply(_e, _g.concat([__spreadArray.apply(void 0, _h.concat([__read.apply(void 0, [(_j.sent()).map(function (pipeline) {
|
|
12144
|
+
// TODO: [🌗]
|
|
12145
|
+
return ({ fileName: fileName, sourceFile: sourceFile, pipeline: __assign(__assign({}, pipeline), { sourceFile: sourceFile }) });
|
|
12146
|
+
})]), false]))]));
|
|
12085
12147
|
return [3 /*break*/, 7];
|
|
12086
12148
|
case 6:
|
|
12087
12149
|
if (isVerbose) {
|
|
12088
12150
|
console.info(colors.gray("Skipped file ".concat(fileName.split('\\').join('/'), " \u2013\u2060\u2060\u2060\u2060\u2060\u2060\u2060\u2060\u2060\u2060\u2060\u2060\u2060\u2060\u2060\u2060 Not a book")));
|
|
12089
12151
|
}
|
|
12090
|
-
|
|
12091
|
-
case 7:
|
|
12092
|
-
// ---
|
|
12093
|
-
if (pipeline !== null) {
|
|
12094
|
-
if (rootUrl !== undefined) {
|
|
12095
|
-
if (pipeline.pipelineUrl === undefined) {
|
|
12096
|
-
pipelineUrl = rootUrl + '/' + relative(rootPath, fileName).split('\\').join('/');
|
|
12097
|
-
// console.log({ pipelineUrl, rootPath, rootUrl, fileName });
|
|
12098
|
-
if (isVerbose) {
|
|
12099
|
-
console.info(colors.yellow("Implicitly set pipeline URL to ".concat(pipelineUrl, " from ").concat(fileName
|
|
12100
|
-
.split('\\')
|
|
12101
|
-
.join('/'))));
|
|
12102
|
-
}
|
|
12103
|
-
pipeline = __assign(__assign({}, pipeline), { pipelineUrl: pipelineUrl });
|
|
12104
|
-
}
|
|
12105
|
-
else if (!pipeline.pipelineUrl.startsWith(rootUrl)) {
|
|
12106
|
-
throw new PipelineUrlError(spaceTrim("\n Pipeline with URL ".concat(pipeline.pipelineUrl, " is not a child of the root URL ").concat(rootUrl, " \uD83C\uDF4F\n\n File:\n ").concat(sourceFile || 'Unknown', "\n\n ")));
|
|
12107
|
-
}
|
|
12108
|
-
}
|
|
12109
|
-
// TODO: [👠] DRY
|
|
12110
|
-
if (pipeline.pipelineUrl === undefined) {
|
|
12111
|
-
if (isVerbose) {
|
|
12112
|
-
console.info(colors.yellow("Can not load pipeline from ".concat(fileName
|
|
12113
|
-
.split('\\')
|
|
12114
|
-
.join('/'), " because of missing URL")));
|
|
12115
|
-
}
|
|
12116
|
-
}
|
|
12117
|
-
else {
|
|
12118
|
-
// Note: [🐨] Pipeline is checked multiple times
|
|
12119
|
-
// TODO: Maybe once is enough BUT be sure to check it - better to check it multiple times than not at all
|
|
12120
|
-
validatePipeline(pipeline);
|
|
12121
|
-
if (
|
|
12122
|
-
// TODO: [🐽] comparePipelines(pipeline1,pipeline2): 'IDENTICAL' |'IDENTICAL_UNPREPARED' | 'IDENTICAL_INTERFACE' | 'DIFFERENT'
|
|
12123
|
-
!collection.has(pipeline.pipelineUrl)) {
|
|
12124
|
-
if (isVerbose) {
|
|
12125
|
-
console.info(colors.green("Loaded pipeline ".concat(fileName.split('\\').join('/'), "\u2060\u2060\u2060\u2060\u2060\u2060\u2060\u2060\u2060\u2060\u2060\u2060")));
|
|
12126
|
-
}
|
|
12127
|
-
// Note: [🦄] Pipeline with same url uniqueness will be double-checked automatically in SimplePipelineCollection
|
|
12128
|
-
collection.set(pipeline.pipelineUrl, pipeline);
|
|
12129
|
-
}
|
|
12130
|
-
else if (pipelineJsonToString(unpreparePipeline(pipeline)) ===
|
|
12131
|
-
pipelineJsonToString(unpreparePipeline(collection.get(pipeline.pipelineUrl)))) {
|
|
12132
|
-
if (isVerbose) {
|
|
12133
|
-
console.info(colors.gray("Skipped pipeline ".concat(fileName
|
|
12134
|
-
.split('\\')
|
|
12135
|
-
.join('/'), " \u2013\u2060\u2060\u2060\u2060\u2060\u2060\u2060\u2060\u2060\u2060\u2060\u2060\u2060\u2060\u2060\u2060 Already identical pipeline in the collection")));
|
|
12136
|
-
}
|
|
12137
|
-
}
|
|
12138
|
-
else {
|
|
12139
|
-
existing = collection.get(pipeline.pipelineUrl);
|
|
12140
|
-
throw new PipelineUrlError(spaceTrim("\n Pipeline with URL ".concat(pipeline.pipelineUrl, " is already in the collection \uD83C\uDF4F\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 ")));
|
|
12141
|
-
}
|
|
12142
|
-
}
|
|
12143
|
-
}
|
|
12144
|
-
return [3 /*break*/, 9];
|
|
12152
|
+
_j.label = 7;
|
|
12153
|
+
case 7: return [3 /*break*/, 9];
|
|
12145
12154
|
case 8:
|
|
12146
|
-
error_1 =
|
|
12155
|
+
error_1 = _j.sent();
|
|
12147
12156
|
if (!(error_1 instanceof Error)) {
|
|
12148
12157
|
throw error_1;
|
|
12149
12158
|
}
|
|
@@ -12158,24 +12167,24 @@ function createCollectionFromDirectory(rootPath, tools, options) {
|
|
|
12158
12167
|
}
|
|
12159
12168
|
});
|
|
12160
12169
|
};
|
|
12161
|
-
|
|
12170
|
+
_c.label = 2;
|
|
12162
12171
|
case 2:
|
|
12163
|
-
|
|
12172
|
+
_c.trys.push([2, 7, 8, 9]);
|
|
12164
12173
|
fileNames_1 = __values(fileNames), fileNames_1_1 = fileNames_1.next();
|
|
12165
|
-
|
|
12174
|
+
_c.label = 3;
|
|
12166
12175
|
case 3:
|
|
12167
12176
|
if (!!fileNames_1_1.done) return [3 /*break*/, 6];
|
|
12168
12177
|
fileName = fileNames_1_1.value;
|
|
12169
12178
|
return [5 /*yield**/, _loop_1(fileName)];
|
|
12170
12179
|
case 4:
|
|
12171
|
-
|
|
12172
|
-
|
|
12180
|
+
_c.sent();
|
|
12181
|
+
_c.label = 5;
|
|
12173
12182
|
case 5:
|
|
12174
12183
|
fileNames_1_1 = fileNames_1.next();
|
|
12175
12184
|
return [3 /*break*/, 3];
|
|
12176
12185
|
case 6: return [3 /*break*/, 9];
|
|
12177
12186
|
case 7:
|
|
12178
|
-
e_1_1 =
|
|
12187
|
+
e_1_1 = _c.sent();
|
|
12179
12188
|
e_1 = { error: e_1_1 };
|
|
12180
12189
|
return [3 /*break*/, 9];
|
|
12181
12190
|
case 8:
|
|
@@ -12184,7 +12193,86 @@ function createCollectionFromDirectory(rootPath, tools, options) {
|
|
|
12184
12193
|
}
|
|
12185
12194
|
finally { if (e_1) throw e_1.error; }
|
|
12186
12195
|
return [7 /*endfinally*/];
|
|
12187
|
-
case 9:
|
|
12196
|
+
case 9:
|
|
12197
|
+
_loop_2 = function (pipelineWithFilenames) {
|
|
12198
|
+
var fileName = pipelineWithFilenames.fileName, sourceFile = pipelineWithFilenames.sourceFile;
|
|
12199
|
+
var pipeline = pipelineWithFilenames.pipeline;
|
|
12200
|
+
try {
|
|
12201
|
+
if (rootUrl !== undefined) {
|
|
12202
|
+
if (pipeline.pipelineUrl === undefined) {
|
|
12203
|
+
var pipelineUrl = rootUrl + '/' + relative(rootPath, fileName).split('\\').join('/');
|
|
12204
|
+
// console.log({ pipelineUrl, rootPath, rootUrl, fileName });
|
|
12205
|
+
if (isVerbose) {
|
|
12206
|
+
console.info(colors.yellow("Implicitly set pipeline URL to ".concat(pipelineUrl, " from ").concat(fileName
|
|
12207
|
+
.split('\\')
|
|
12208
|
+
.join('/'))));
|
|
12209
|
+
}
|
|
12210
|
+
pipeline = __assign(__assign({}, pipeline), { pipelineUrl: pipelineUrl });
|
|
12211
|
+
}
|
|
12212
|
+
else if (!pipeline.pipelineUrl.startsWith(rootUrl)) {
|
|
12213
|
+
throw new PipelineUrlError(spaceTrim("\n Pipeline with URL ".concat(pipeline.pipelineUrl, " is not a child of the root URL ").concat(rootUrl, " \uD83C\uDF4F\n\n File:\n ").concat(sourceFile || 'Unknown', "\n\n ")));
|
|
12214
|
+
}
|
|
12215
|
+
}
|
|
12216
|
+
// TODO: [👠] DRY
|
|
12217
|
+
if (pipeline.pipelineUrl === undefined) {
|
|
12218
|
+
if (isVerbose) {
|
|
12219
|
+
console.info(colors.yellow("Can not load pipeline from ".concat(fileName.split('\\').join('/'), " because of missing URL")));
|
|
12220
|
+
}
|
|
12221
|
+
}
|
|
12222
|
+
else {
|
|
12223
|
+
// Note: [🐨] Pipeline is checked multiple times
|
|
12224
|
+
// TODO: Maybe once is enough BUT be sure to check it - better to check it multiple times than not at all
|
|
12225
|
+
validatePipeline(pipeline);
|
|
12226
|
+
if (
|
|
12227
|
+
// TODO: [🐽] comparePipelines(pipeline1,pipeline2): 'IDENTICAL' |'IDENTICAL_UNPREPARED' | 'IDENTICAL_INTERFACE' | 'DIFFERENT'
|
|
12228
|
+
!collection.has(pipeline.pipelineUrl)) {
|
|
12229
|
+
if (isVerbose) {
|
|
12230
|
+
console.info(colors.green("Loaded pipeline ".concat(fileName.split('\\').join('/'), "\u2060\u2060\u2060\u2060\u2060\u2060\u2060\u2060\u2060\u2060\u2060\u2060")));
|
|
12231
|
+
}
|
|
12232
|
+
// Note: [🦄] Pipeline with same url uniqueness will be double-checked automatically in SimplePipelineCollection
|
|
12233
|
+
collection.set(pipeline.pipelineUrl, pipeline);
|
|
12234
|
+
}
|
|
12235
|
+
else if (pipelineJsonToString(unpreparePipeline(pipeline)) ===
|
|
12236
|
+
pipelineJsonToString(unpreparePipeline(collection.get(pipeline.pipelineUrl)))) {
|
|
12237
|
+
if (isVerbose) {
|
|
12238
|
+
console.info(colors.gray("Skipped pipeline ".concat(fileName
|
|
12239
|
+
.split('\\')
|
|
12240
|
+
.join('/'), " \u2013\u2060\u2060\u2060\u2060\u2060\u2060\u2060\u2060\u2060\u2060\u2060\u2060\u2060\u2060\u2060\u2060 Already identical pipeline in the collection")));
|
|
12241
|
+
}
|
|
12242
|
+
}
|
|
12243
|
+
else {
|
|
12244
|
+
var existing = collection.get(pipeline.pipelineUrl);
|
|
12245
|
+
throw new PipelineUrlError(spaceTrim("\n Pipeline with URL ".concat(pipeline.pipelineUrl, " is already in the collection \uD83C\uDF4F\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 ")));
|
|
12246
|
+
}
|
|
12247
|
+
}
|
|
12248
|
+
}
|
|
12249
|
+
catch (error) {
|
|
12250
|
+
if (!(error instanceof Error)) {
|
|
12251
|
+
throw error;
|
|
12252
|
+
}
|
|
12253
|
+
// TODO: [7] DRY
|
|
12254
|
+
var wrappedErrorMessage = spaceTrim(function (block) { return "\n ".concat(error.name, " in pipeline ").concat(fileName.split('\\').join('/'), "\u2060:\n\n Original error message:\n ").concat(block(error.message), "\n\n Original stack trace:\n ").concat(block(error.stack || ''), "\n\n ---\n\n "); }) + '\n';
|
|
12255
|
+
if (isCrashedOnError) {
|
|
12256
|
+
throw new CollectionError(wrappedErrorMessage);
|
|
12257
|
+
}
|
|
12258
|
+
// TODO: [🟥] Detect browser / node and make it colorfull
|
|
12259
|
+
console.error(wrappedErrorMessage);
|
|
12260
|
+
}
|
|
12261
|
+
};
|
|
12262
|
+
try {
|
|
12263
|
+
for (pipelinesWithFilenames_1 = __values(pipelinesWithFilenames), pipelinesWithFilenames_1_1 = pipelinesWithFilenames_1.next(); !pipelinesWithFilenames_1_1.done; pipelinesWithFilenames_1_1 = pipelinesWithFilenames_1.next()) {
|
|
12264
|
+
pipelineWithFilenames = pipelinesWithFilenames_1_1.value;
|
|
12265
|
+
_loop_2(pipelineWithFilenames);
|
|
12266
|
+
}
|
|
12267
|
+
}
|
|
12268
|
+
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
12269
|
+
finally {
|
|
12270
|
+
try {
|
|
12271
|
+
if (pipelinesWithFilenames_1_1 && !pipelinesWithFilenames_1_1.done && (_b = pipelinesWithFilenames_1.return)) _b.call(pipelinesWithFilenames_1);
|
|
12272
|
+
}
|
|
12273
|
+
finally { if (e_2) throw e_2.error; }
|
|
12274
|
+
}
|
|
12275
|
+
return [2 /*return*/, Array.from(collection.values())];
|
|
12188
12276
|
}
|
|
12189
12277
|
});
|
|
12190
12278
|
}); });
|
|
@@ -12203,6 +12291,59 @@ function createCollectionFromDirectory(rootPath, tools, options) {
|
|
|
12203
12291
|
* TODO: Maybe move from `@promptbook/node` to `@promptbook/core` as we removes direct dependency on `fs`
|
|
12204
12292
|
*/
|
|
12205
12293
|
|
|
12294
|
+
/**
|
|
12295
|
+
* Saves the given books into an archive file with `.bookc` extension
|
|
12296
|
+
*
|
|
12297
|
+
* @param filePath Path to the archive file with `.bookc` extension
|
|
12298
|
+
* @param books Pipelines to be saved in the archive
|
|
12299
|
+
* @param fs Filesystem tools
|
|
12300
|
+
*
|
|
12301
|
+
* @private utility of Prompbook
|
|
12302
|
+
*/
|
|
12303
|
+
function saveArchive(filePath, collectionJson, fs) {
|
|
12304
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
12305
|
+
var collectionJson_1, collectionJson_1_1, pipelineJson, archive, collectionJsonString, data;
|
|
12306
|
+
var e_1, _a;
|
|
12307
|
+
return __generator(this, function (_b) {
|
|
12308
|
+
switch (_b.label) {
|
|
12309
|
+
case 0:
|
|
12310
|
+
if (!filePath.endsWith('.bookc')) {
|
|
12311
|
+
throw new UnexpectedError("Archive file must have '.bookc' extension");
|
|
12312
|
+
}
|
|
12313
|
+
try {
|
|
12314
|
+
// Note: We want to ensure that the generated JSONs are logically correct
|
|
12315
|
+
for (collectionJson_1 = __values(collectionJson), collectionJson_1_1 = collectionJson_1.next(); !collectionJson_1_1.done; collectionJson_1_1 = collectionJson_1.next()) {
|
|
12316
|
+
pipelineJson = collectionJson_1_1.value;
|
|
12317
|
+
validatePipeline(pipelineJson);
|
|
12318
|
+
}
|
|
12319
|
+
}
|
|
12320
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
12321
|
+
finally {
|
|
12322
|
+
try {
|
|
12323
|
+
if (collectionJson_1_1 && !collectionJson_1_1.done && (_a = collectionJson_1.return)) _a.call(collectionJson_1);
|
|
12324
|
+
}
|
|
12325
|
+
finally { if (e_1) throw e_1.error; }
|
|
12326
|
+
}
|
|
12327
|
+
archive = new JSZip();
|
|
12328
|
+
collectionJsonString = stringifyPipelineJson(collectionJson);
|
|
12329
|
+
archive.file('index.book.json', collectionJsonString);
|
|
12330
|
+
return [4 /*yield*/, archive.generateAsync({ type: 'nodebuffer', streamFiles: true })];
|
|
12331
|
+
case 1:
|
|
12332
|
+
data = _b.sent();
|
|
12333
|
+
return [4 /*yield*/, fs.writeFile(filePath, data)];
|
|
12334
|
+
case 2:
|
|
12335
|
+
_b.sent();
|
|
12336
|
+
return [2 /*return*/];
|
|
12337
|
+
}
|
|
12338
|
+
});
|
|
12339
|
+
});
|
|
12340
|
+
}
|
|
12341
|
+
/**
|
|
12342
|
+
* TODO: Add metadata to zip
|
|
12343
|
+
* TODO: Compression level and other zip options from config
|
|
12344
|
+
* Note: [🟢] Code in this file should never be never released in packages that could be imported into browser environment
|
|
12345
|
+
*/
|
|
12346
|
+
|
|
12206
12347
|
/**
|
|
12207
12348
|
* Function usageToWorktime will take usage and estimate saved worktime in hours of reading / writing
|
|
12208
12349
|
*
|
|
@@ -12298,7 +12439,7 @@ function $initializeMakeCommand(program) {
|
|
|
12298
12439
|
makeCommand.action(function (path, _a) {
|
|
12299
12440
|
var projectName = _a.projectName, rootUrl = _a.rootUrl, format = _a.format, functionName = _a.functionName, validation = _a.validation, isCacheReloaded = _a.reload, isVerbose = _a.verbose, output = _a.output;
|
|
12300
12441
|
return __awaiter(_this, void 0, void 0, function () {
|
|
12301
|
-
var formats, validations, prepareAndScrapeOptions, fs, llm, executables, tools, collection, pipelinesUrls, validations_1, validations_1_1, validation_1, pipelinesUrls_1, pipelinesUrls_1_1, pipelineUrl, pipeline, e_1_1, e_2_1, collectionJson, collectionJsonString, collectionJsonItems, saveFile
|
|
12442
|
+
var formats, validations, prepareAndScrapeOptions, fs, llm, executables, tools, collection, pipelinesUrls, validations_1, validations_1_1, validation_1, pipelinesUrls_1, pipelinesUrls_1_1, pipelineUrl, pipeline, e_1_1, e_2_1, collectionJson, collectionJsonString, collectionJsonItems, saveFile;
|
|
12302
12443
|
var _b, e_2, _c, e_1, _d;
|
|
12303
12444
|
var _this = this;
|
|
12304
12445
|
return __generator(this, function (_e) {
|
|
@@ -12434,7 +12575,7 @@ function $initializeMakeCommand(program) {
|
|
|
12434
12575
|
return spaceTrim(collectionJsonString.substring(1, collectionJsonString.length - 1));
|
|
12435
12576
|
})();
|
|
12436
12577
|
saveFile = function (extension, content) { return __awaiter(_this, void 0, void 0, function () {
|
|
12437
|
-
var filename
|
|
12578
|
+
var filename;
|
|
12438
12579
|
return __generator(this, function (_a) {
|
|
12439
12580
|
switch (_a.label) {
|
|
12440
12581
|
case 0:
|
|
@@ -12451,15 +12592,12 @@ function $initializeMakeCommand(program) {
|
|
|
12451
12592
|
return [4 /*yield*/, writeFile(filename, content, 'utf-8')];
|
|
12452
12593
|
case 2:
|
|
12453
12594
|
_a.sent();
|
|
12454
|
-
return [3 /*break*/,
|
|
12455
|
-
case 3: return [4 /*yield*/,
|
|
12595
|
+
return [3 /*break*/, 5];
|
|
12596
|
+
case 3: return [4 /*yield*/, saveArchive(filename, content, fs)];
|
|
12456
12597
|
case 4:
|
|
12457
|
-
data = _a.sent();
|
|
12458
|
-
return [4 /*yield*/, writeFile(filename, data)];
|
|
12459
|
-
case 5:
|
|
12460
12598
|
_a.sent();
|
|
12461
|
-
_a.label =
|
|
12462
|
-
case
|
|
12599
|
+
_a.label = 5;
|
|
12600
|
+
case 5:
|
|
12463
12601
|
// Note: Log despite of verbose mode
|
|
12464
12602
|
console.info(colors.green("Made ".concat(filename.split('\\').join('/'))));
|
|
12465
12603
|
return [2 /*return*/];
|
|
@@ -12468,9 +12606,7 @@ function $initializeMakeCommand(program) {
|
|
|
12468
12606
|
}); };
|
|
12469
12607
|
if (!formats.includes('bookc')) return [3 /*break*/, 22];
|
|
12470
12608
|
formats = formats.filter(function (format) { return format !== 'bookc'; });
|
|
12471
|
-
|
|
12472
|
-
bookcBundle.file('index.book.json', collectionJsonString);
|
|
12473
|
-
return [4 /*yield*/, saveFile('bookc', bookcBundle)];
|
|
12609
|
+
return [4 /*yield*/, saveFile('bookc', collectionJson)];
|
|
12474
12610
|
case 21:
|
|
12475
12611
|
_e.sent();
|
|
12476
12612
|
_e.label = 22;
|
|
@@ -13022,31 +13158,31 @@ function isValidPipelineString(pipelineString) {
|
|
|
13022
13158
|
*/
|
|
13023
13159
|
function $getCompiledBook(tools, pipelineSource, options) {
|
|
13024
13160
|
return __awaiter(this, void 0, void 0, function () {
|
|
13025
|
-
var fs, fetch, filePathRaw, filePath, filePathCandidates, filePathCandidates_1, filePathCandidates_1_1, filePathCandidate, pipelineString, _a, pipelineJson, compiledFilePath,
|
|
13161
|
+
var fs, fetch, filePathRaw, filePath, filePathCandidates, filePathCandidates_1, filePathCandidates_1_1, filePathCandidate, pipelineString, _a, pipelineJson, compiledFilePath, e_1_1, rootDirname, _loop_1, i, state_1, response_1, pipelineString, pipelineJson, pipelineJson;
|
|
13026
13162
|
var e_1, _b;
|
|
13027
13163
|
var _this = this;
|
|
13028
13164
|
return __generator(this, function (_c) {
|
|
13029
13165
|
switch (_c.label) {
|
|
13030
13166
|
case 0:
|
|
13031
13167
|
fs = tools.fs, fetch = tools.fetch;
|
|
13032
|
-
if (!isValidFilePath(pipelineSource)) return [3 /*break*/,
|
|
13168
|
+
if (!isValidFilePath(pipelineSource)) return [3 /*break*/, 11];
|
|
13033
13169
|
filePathRaw = pipelineSource;
|
|
13034
13170
|
filePath = null;
|
|
13035
13171
|
filePathCandidates = [filePathRaw, "".concat(filePathRaw, ".md"), "".concat(filePathRaw, ".book"), "".concat(filePathRaw, ".book")];
|
|
13036
13172
|
filePathCandidates = __spreadArray(__spreadArray([], __read(filePathCandidates), false), __read(filePathCandidates.map(function (path) { return path.split('\\').join('/'); })), false);
|
|
13037
13173
|
_c.label = 1;
|
|
13038
13174
|
case 1:
|
|
13039
|
-
_c.trys.push([1, 10, 11
|
|
13175
|
+
_c.trys.push([1, 9, 10, 11]);
|
|
13040
13176
|
filePathCandidates_1 = __values(filePathCandidates), filePathCandidates_1_1 = filePathCandidates_1.next();
|
|
13041
13177
|
_c.label = 2;
|
|
13042
13178
|
case 2:
|
|
13043
|
-
if (!!filePathCandidates_1_1.done) return [3 /*break*/,
|
|
13179
|
+
if (!!filePathCandidates_1_1.done) return [3 /*break*/, 8];
|
|
13044
13180
|
filePathCandidate = filePathCandidates_1_1.value;
|
|
13045
13181
|
return [4 /*yield*/, isFileExisting(filePathCandidate, fs)
|
|
13046
13182
|
// <- TODO: Also test that among the candidates the file is book not just any file
|
|
13047
13183
|
];
|
|
13048
13184
|
case 3:
|
|
13049
|
-
if (!_c.sent()) return [3 /*break*/,
|
|
13185
|
+
if (!_c.sent()) return [3 /*break*/, 7];
|
|
13050
13186
|
filePath = filePathCandidate;
|
|
13051
13187
|
_a = validatePipelineString;
|
|
13052
13188
|
return [4 /*yield*/, fs.readFile(filePath, 'utf-8')];
|
|
@@ -13056,31 +13192,26 @@ function $getCompiledBook(tools, pipelineSource, options) {
|
|
|
13056
13192
|
case 5:
|
|
13057
13193
|
pipelineJson = _c.sent();
|
|
13058
13194
|
compiledFilePath = filePath.replace('.book.md', '.book').replace('.book', '.bookc');
|
|
13059
|
-
|
|
13060
|
-
bookcBundle.file('index.book.json', JSON.stringify([pipelineJson]));
|
|
13061
|
-
return [4 /*yield*/, bookcBundle.generateAsync({ type: 'nodebuffer', streamFiles: true })];
|
|
13195
|
+
return [4 /*yield*/, saveArchive(compiledFilePath, [pipelineJson], fs)];
|
|
13062
13196
|
case 6:
|
|
13063
|
-
data = _c.sent();
|
|
13064
|
-
return [4 /*yield*/, fs.writeFile(compiledFilePath, data)];
|
|
13065
|
-
case 7:
|
|
13066
13197
|
_c.sent();
|
|
13067
13198
|
return [2 /*return*/, pipelineJson];
|
|
13068
|
-
case
|
|
13199
|
+
case 7:
|
|
13069
13200
|
filePathCandidates_1_1 = filePathCandidates_1.next();
|
|
13070
13201
|
return [3 /*break*/, 2];
|
|
13071
|
-
case
|
|
13072
|
-
case
|
|
13202
|
+
case 8: return [3 /*break*/, 11];
|
|
13203
|
+
case 9:
|
|
13073
13204
|
e_1_1 = _c.sent();
|
|
13074
13205
|
e_1 = { error: e_1_1 };
|
|
13075
|
-
return [3 /*break*/,
|
|
13076
|
-
case
|
|
13206
|
+
return [3 /*break*/, 11];
|
|
13207
|
+
case 10:
|
|
13077
13208
|
try {
|
|
13078
13209
|
if (filePathCandidates_1_1 && !filePathCandidates_1_1.done && (_b = filePathCandidates_1.return)) _b.call(filePathCandidates_1);
|
|
13079
13210
|
}
|
|
13080
13211
|
finally { if (e_1) throw e_1.error; }
|
|
13081
13212
|
return [7 /*endfinally*/];
|
|
13082
|
-
case
|
|
13083
|
-
if (!isValidPipelineUrl(pipelineSource)) return [3 /*break*/,
|
|
13213
|
+
case 11:
|
|
13214
|
+
if (!isValidPipelineUrl(pipelineSource)) return [3 /*break*/, 15];
|
|
13084
13215
|
rootDirname = process.cwd();
|
|
13085
13216
|
_loop_1 = function (i) {
|
|
13086
13217
|
var booksDirname, collection_1, pipeline;
|
|
@@ -13131,47 +13262,47 @@ function $getCompiledBook(tools, pipelineSource, options) {
|
|
|
13131
13262
|
});
|
|
13132
13263
|
};
|
|
13133
13264
|
i = 0;
|
|
13134
|
-
_c.label =
|
|
13135
|
-
case
|
|
13136
|
-
if (!(i < LOOP_LIMIT)) return [3 /*break*/,
|
|
13265
|
+
_c.label = 12;
|
|
13266
|
+
case 12:
|
|
13267
|
+
if (!(i < LOOP_LIMIT)) return [3 /*break*/, 15];
|
|
13137
13268
|
return [5 /*yield**/, _loop_1(i)];
|
|
13138
|
-
case
|
|
13269
|
+
case 13:
|
|
13139
13270
|
state_1 = _c.sent();
|
|
13140
13271
|
if (typeof state_1 === "object")
|
|
13141
13272
|
return [2 /*return*/, state_1.value];
|
|
13142
13273
|
switch (state_1) {
|
|
13143
|
-
case "break-up_to_root": return [3 /*break*/,
|
|
13274
|
+
case "break-up_to_root": return [3 /*break*/, 15];
|
|
13144
13275
|
}
|
|
13145
|
-
_c.label =
|
|
13146
|
-
case
|
|
13276
|
+
_c.label = 14;
|
|
13277
|
+
case 14:
|
|
13147
13278
|
i++;
|
|
13148
|
-
return [3 /*break*/,
|
|
13149
|
-
case
|
|
13150
|
-
if (!isValidPipelineUrl(pipelineSource)) return [3 /*break*/,
|
|
13279
|
+
return [3 /*break*/, 12];
|
|
13280
|
+
case 15:
|
|
13281
|
+
if (!isValidPipelineUrl(pipelineSource)) return [3 /*break*/, 19];
|
|
13151
13282
|
return [4 /*yield*/, fetch(pipelineSource)];
|
|
13152
|
-
case
|
|
13283
|
+
case 16:
|
|
13153
13284
|
response_1 = _c.sent();
|
|
13154
13285
|
if (response_1.status >= 300) {
|
|
13155
13286
|
throw new NotFoundError(spaceTrim(function (block) { return "\n Book not found on URL:\n ".concat(block(pipelineSource), "\n\n Request failed with status ").concat(block(response_1.status.toString()), " ").concat(block(response_1.statusText), "\n "); }));
|
|
13156
13287
|
}
|
|
13157
13288
|
return [4 /*yield*/, response_1.text()];
|
|
13158
|
-
case
|
|
13289
|
+
case 17:
|
|
13159
13290
|
pipelineString = _c.sent();
|
|
13160
13291
|
// console.log({ pipelineString });
|
|
13161
13292
|
if (!isValidPipelineString(pipelineString)) {
|
|
13162
13293
|
throw new NotFoundError(spaceTrim(function (block) { return "\n Book not found on URL:\n ".concat(block(pipelineSource), "\n\n Requested URL does not seem to contain a valid book\n "); }));
|
|
13163
13294
|
}
|
|
13164
13295
|
return [4 /*yield*/, compilePipeline(pipelineString, tools, __assign({ rootDirname: null }, options))];
|
|
13165
|
-
case
|
|
13296
|
+
case 18:
|
|
13166
13297
|
pipelineJson = _c.sent();
|
|
13167
13298
|
return [2 /*return*/, pipelineJson];
|
|
13168
|
-
case
|
|
13169
|
-
if (!isValidPipelineString(pipelineSource)) return [3 /*break*/,
|
|
13299
|
+
case 19:
|
|
13300
|
+
if (!isValidPipelineString(pipelineSource)) return [3 /*break*/, 21];
|
|
13170
13301
|
return [4 /*yield*/, compilePipeline(pipelineSource, tools, __assign({ rootDirname: null }, options))];
|
|
13171
|
-
case
|
|
13302
|
+
case 20:
|
|
13172
13303
|
pipelineJson = _c.sent();
|
|
13173
13304
|
return [2 /*return*/, pipelineJson];
|
|
13174
|
-
case
|
|
13305
|
+
case 21: /* not else */ throw new NotFoundError(spaceTrim(function (block) { return "\n Book not found:\n ".concat(block(pipelineSource), "\n\n Pipelines can be loaded from:\n 1) As a file ./books/write-cv.book\n 2) As a URL https://promptbook.studio/hejny/write-cv.book found in ./books folder recursively\n 2) As a URL https://promptbook.studio/hejny/write-cv.book fetched from the internet\n 3) As a string\n\n\n "); }));
|
|
13175
13306
|
}
|
|
13176
13307
|
});
|
|
13177
13308
|
});
|