@promptbook/cli 0.59.0-32 → 0.59.0-34

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/esm/index.es.js CHANGED
@@ -143,7 +143,7 @@ new Function("\n try {\n if (typeof WorkerGlobalScope !== 'undefined'
143
143
  /**
144
144
  * The version of the Promptbook library
145
145
  */
146
- var PROMPTBOOK_VERSION = '0.59.0-31';
146
+ var PROMPTBOOK_VERSION = '0.59.0-33';
147
147
 
148
148
  /**
149
149
  * Initializes testing `hello` command for Promptbook CLI utilities
@@ -437,7 +437,7 @@ function validatePromptbook(promptbook) {
437
437
  * > ex port function validatePromptbook(promptbook: unknown): asserts promptbook is PromptbookJson {
438
438
  */
439
439
 
440
- var promptbookLibrary = [{title:"Prepare Keywords",promptbookUrl:"https://promptbook.studio/promptbook/prepare-keywords.ptbk.md",promptbookVersion:"0.59.0-31",parameters:[{name:"content",description:"The content",isInput:true,isOutput:false},{name:"keywords",description:"Keywords separated by comma",isInput:false,isOutput:true}],promptTemplates:[{name:"knowledge",title:"Knowledge",dependentParameterNames:["content"],executionType:"PROMPT_TEMPLATE",modelRequirements:{modelVariant:"CHAT",modelName:"claude-3-opus-20240229"},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> {content}",resultingParameterName:"keywords"}],knowledge:[]},{title:"Prepare Knowledge from Markdown",promptbookUrl:"https://promptbook.studio/promptbook/prepare-knowledge-from-markdown.ptbk.md",promptbookVersion:"0.59.0-31",parameters:[{name:"content",description:"Markdown document content",isInput:true,isOutput:false},{name:"knowledge",description:"The knowledge JSON object",isInput:false,isOutput:true}],promptTemplates:[{name:"knowledge",title:"Knowledge",dependentParameterNames:["content"],executionType:"PROMPT_TEMPLATE",modelRequirements:{modelVariant:"CHAT",modelName:"claude-3-opus-20240229"},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> {content}",resultingParameterName:"knowledge"}],knowledge:[]}];
440
+ var promptbookLibrary = [{title:"Prepare Keywords",promptbookUrl:"https://promptbook.studio/promptbook/prepare-keywords.ptbk.md",promptbookVersion:"0.59.0-33",parameters:[{name:"content",description:"The content",isInput:true,isOutput:false},{name:"keywords",description:"Keywords separated by comma",isInput:false,isOutput:true}],promptTemplates:[{name:"knowledge",title:"Knowledge",dependentParameterNames:["content"],executionType:"PROMPT_TEMPLATE",modelRequirements:{modelVariant:"CHAT",modelName:"claude-3-opus-20240229"},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> {content}",resultingParameterName:"keywords"}],knowledge:[]},{title:"Prepare Knowledge from Markdown",promptbookUrl:"https://promptbook.studio/promptbook/prepare-knowledge-from-markdown.ptbk.md",promptbookVersion:"0.59.0-33",parameters:[{name:"content",description:"Markdown document content",isInput:true,isOutput:false},{name:"knowledge",description:"The knowledge JSON object",isInput:false,isOutput:true}],promptTemplates:[{name:"knowledge",title:"Knowledge",dependentParameterNames:["content"],executionType:"PROMPT_TEMPLATE",modelRequirements:{modelVariant:"CHAT",modelName:"claude-3-opus-20240229"},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> {content}",resultingParameterName:"knowledge"}],knowledge:[]}];
441
441
 
442
442
  /**
443
443
  * This error indicates errors during the execution of the promptbook
@@ -2938,9 +2938,279 @@ function titleToName(value) {
2938
2938
  return value;
2939
2939
  }
2940
2940
 
2941
+ /**
2942
+ * Compile promptbook from string (markdown) format to JSON format synchronously
2943
+ *
2944
+ * Note: There are two similar functions:
2945
+ * - `promptbookStringToJson` **(preferred)** - which propperly compiles the promptbook and use embedding for external knowledge
2946
+ * - `promptbookStringToJsonSync` - use only if you need to compile promptbook synchronously and it contains NO external knowledge
2947
+ *
2948
+ * @param promptbookString {Promptbook} in string markdown format (.ptbk.md)
2949
+ * @param options - Options and tools for the compilation
2950
+ * @returns {Promptbook} compiled in JSON format (.ptbk.json)
2951
+ * @throws {PromptbookSyntaxError} if the promptbook string is not valid
2952
+ *
2953
+ * Note: This function does not validate logic of the pipeline only the syntax
2954
+ * Note: This function acts as compilation process
2955
+ */
2956
+ function promptbookStringToJsonSync(promptbookString) {
2957
+ var e_1, _a, e_2, _b;
2958
+ var promptbookJson = {
2959
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
2960
+ title: undefined /* <- Note: Putting here placeholder to keep `title` on top at final JSON */,
2961
+ promptbookUrl: undefined /* <- Note: Putting here placeholder to keep `promptbookUrl` on top at final JSON */,
2962
+ promptbookVersion: PROMPTBOOK_VERSION,
2963
+ description: undefined /* <- Note: Putting here placeholder to keep `description` on top at final JSON */,
2964
+ parameters: [],
2965
+ promptTemplates: [],
2966
+ knowledge: [],
2967
+ };
2968
+ // =============================================================
2969
+ // Note: 1️⃣ Normalization of the PROMPTBOOK string
2970
+ promptbookString = removeContentComments(promptbookString);
2971
+ promptbookString = promptbookString.replaceAll(/`\{(?<parameterName>[a-z0-9_]+)\}`/gi, '{$<parameterName>}');
2972
+ promptbookString = promptbookString.replaceAll(/`->\s+\{(?<parameterName>[a-z0-9_]+)\}`/gi, '-> {$<parameterName>}');
2973
+ // =============================================================
2974
+ ///Note: 2️⃣ Function for adding parameters
2975
+ var addParam = function (parameterCommand) {
2976
+ var parameterName = parameterCommand.parameterName, parameterDescription = parameterCommand.parameterDescription, isInput = parameterCommand.isInput, isOutput = parameterCommand.isOutput;
2977
+ var existingParameter = promptbookJson.parameters.find(function (parameter) { return parameter.name === parameterName; });
2978
+ if (existingParameter &&
2979
+ existingParameter.description &&
2980
+ existingParameter.description !== parameterDescription &&
2981
+ parameterDescription) {
2982
+ throw new PromptbookSyntaxError(spaceTrim$1(function (block) { return "\n Parameter {".concat(parameterName, "} is defined multiple times with different description.\n\n First definition:\n ").concat(block(existingParameter.description || '[undefined]'), "\n\n Second definition:\n ").concat(block(parameterDescription || '[undefined]'), "\n "); }));
2983
+ }
2984
+ if (existingParameter) {
2985
+ if (parameterDescription) {
2986
+ existingParameter.description = parameterDescription;
2987
+ }
2988
+ }
2989
+ else {
2990
+ promptbookJson.parameters.push({
2991
+ name: parameterName,
2992
+ description: parameterDescription || undefined,
2993
+ isInput: isInput,
2994
+ isOutput: isOutput,
2995
+ });
2996
+ }
2997
+ };
2998
+ // =============================================================
2999
+ // Note: 3️⃣ Parse the dynamic part - the template pipeline
3000
+ var markdownStructure = markdownToMarkdownStructure(promptbookString);
3001
+ var markdownStructureDeepness = countMarkdownStructureDeepness(markdownStructure);
3002
+ if (markdownStructureDeepness !== 2) {
3003
+ throw new PromptbookSyntaxError(spaceTrim$1("\n Invalid markdown structure.\n The markdown must have exactly 2 levels of headings (one top-level section and one section for each template).\n Now it has ".concat(markdownStructureDeepness, " levels of headings.\n ")));
3004
+ }
3005
+ promptbookJson.title = markdownStructure.title;
3006
+ // TODO: [1] DRY description
3007
+ var description = markdownStructure.content;
3008
+ // Note: Remove codeblocks
3009
+ description = description.split(/^```.*^```/gms).join('');
3010
+ //Note: Remove lists and return statement
3011
+ description = description.split(/^(?:(?:-)|(?:\d\))|(?:`?->))\s+.*$/gm).join('');
3012
+ description = spaceTrim$1(description);
3013
+ if (description === '') {
3014
+ description = undefined;
3015
+ }
3016
+ promptbookJson.description = description;
3017
+ var defaultModelRequirements = {};
3018
+ var listItems = extractAllListItemsFromMarkdown(markdownStructure.content);
3019
+ try {
3020
+ for (var listItems_1 = __values(listItems), listItems_1_1 = listItems_1.next(); !listItems_1_1.done; listItems_1_1 = listItems_1.next()) {
3021
+ var listItem = listItems_1_1.value;
3022
+ var command = parseCommand(listItem);
3023
+ switch (command.type) {
3024
+ case 'PROMPTBOOK_URL':
3025
+ promptbookJson.promptbookUrl = command.promptbookUrl.href;
3026
+ break;
3027
+ case 'PROMPTBOOK_VERSION':
3028
+ promptbookJson.promptbookVersion = command.promptbookVersion;
3029
+ break;
3030
+ case 'MODEL':
3031
+ defaultModelRequirements[command.key] = command.value;
3032
+ break;
3033
+ case 'PARAMETER':
3034
+ addParam(command);
3035
+ break;
3036
+ default:
3037
+ throw new PromptbookSyntaxError("Command ".concat(command.type, " is not allowed in the head of the promptbook ONLY at the prompt template block"));
3038
+ }
3039
+ }
3040
+ }
3041
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
3042
+ finally {
3043
+ try {
3044
+ if (listItems_1_1 && !listItems_1_1.done && (_a = listItems_1.return)) _a.call(listItems_1);
3045
+ }
3046
+ finally { if (e_1) throw e_1.error; }
3047
+ }
3048
+ var _loop_1 = function (section) {
3049
+ var e_3, _e;
3050
+ // TODO: Parse prompt template description (the content out of the codeblock and lists)
3051
+ var templateModelRequirements = __assign({}, defaultModelRequirements);
3052
+ var listItems_3 = extractAllListItemsFromMarkdown(section.content);
3053
+ var dependentParameterNames = new Set();
3054
+ var executionType = 'PROMPT_TEMPLATE';
3055
+ var jokers = [];
3056
+ var postprocessing = [];
3057
+ var expectAmount = {};
3058
+ var expectFormat = undefined;
3059
+ var isExecutionTypeChanged = false;
3060
+ try {
3061
+ for (var listItems_2 = (e_3 = void 0, __values(listItems_3)), listItems_2_1 = listItems_2.next(); !listItems_2_1.done; listItems_2_1 = listItems_2.next()) {
3062
+ var listItem = listItems_2_1.value;
3063
+ var command = parseCommand(listItem);
3064
+ switch (command.type) {
3065
+ case 'JOKER':
3066
+ jokers.push(command.parameterName);
3067
+ dependentParameterNames.add(command.parameterName);
3068
+ break;
3069
+ case 'EXECUTE':
3070
+ if (isExecutionTypeChanged) {
3071
+ throw new PromptbookSyntaxError('Execution type is already defined in the prompt template. It can be defined only once.');
3072
+ }
3073
+ executionType = command.executionType;
3074
+ isExecutionTypeChanged = true;
3075
+ break;
3076
+ case 'MODEL':
3077
+ templateModelRequirements[command.key] = command.value;
3078
+ break;
3079
+ case 'PARAMETER':
3080
+ // Note: This is just for detecting resulitng parameter name
3081
+ addParam(command);
3082
+ break;
3083
+ case 'POSTPROCESS':
3084
+ postprocessing.push(command.functionName);
3085
+ break;
3086
+ case 'EXPECT_AMOUNT':
3087
+ // eslint-disable-next-line no-case-declarations
3088
+ var unit = command.unit.toLowerCase();
3089
+ expectAmount[unit] = expectAmount[unit] || {};
3090
+ if (command.sign === 'MINIMUM' || command.sign === 'EXACTLY') {
3091
+ if (expectAmount[unit].min !== undefined) {
3092
+ throw new PromptbookSyntaxError("Already defined minumum ".concat(expectAmount[unit].min, " ").concat(command.unit.toLowerCase(), ", now trying to redefine it to ").concat(command.amount));
3093
+ }
3094
+ expectAmount[unit].min = command.amount;
3095
+ } /* not else */
3096
+ if (command.sign === 'MAXIMUM' || command.sign === 'EXACTLY') {
3097
+ if (expectAmount[unit].max !== undefined) {
3098
+ throw new PromptbookSyntaxError("Already defined maximum ".concat(expectAmount[unit].max, " ").concat(command.unit.toLowerCase(), ", now trying to redefine it to ").concat(command.amount));
3099
+ }
3100
+ expectAmount[unit].max = command.amount;
3101
+ }
3102
+ break;
3103
+ case 'EXPECT_FORMAT':
3104
+ if (expectFormat !== undefined && command.format !== expectFormat) {
3105
+ throw new PromptbookSyntaxError("Expect format is already defined to \"".concat(expectFormat, "\". Now you try to redefine it by \"").concat(command.format, "\"."));
3106
+ }
3107
+ expectFormat = command.format;
3108
+ break;
3109
+ default:
3110
+ throw new PromptbookSyntaxError("Command ".concat(command.type, " is not allowed in the block of the prompt template ONLY at the head of the promptbook"));
3111
+ }
3112
+ }
3113
+ }
3114
+ catch (e_3_1) { e_3 = { error: e_3_1 }; }
3115
+ finally {
3116
+ try {
3117
+ if (listItems_2_1 && !listItems_2_1.done && (_e = listItems_2.return)) _e.call(listItems_2);
3118
+ }
3119
+ finally { if (e_3) throw e_3.error; }
3120
+ }
3121
+ var _f = extractOneBlockFromMarkdown(section.content), language = _f.language, content = _f.content;
3122
+ if (executionType === 'SCRIPT') {
3123
+ if (!language) {
3124
+ throw new PromptbookSyntaxError('You must specify the language of the script in the prompt template');
3125
+ }
3126
+ else if (!SUPPORTED_SCRIPT_LANGUAGES.includes(language)) {
3127
+ throw new PromptbookSyntaxError(spaceTrim$1(function (block) { return "\n Script language ".concat(language, " is not supported.\n\n Supported languages are:\n ").concat(block(SUPPORTED_SCRIPT_LANGUAGES.join(', ')), "\n\n "); }));
3128
+ }
3129
+ }
3130
+ var lastLine = section.content.split('\n').pop();
3131
+ var match = /^->\s*\{(?<resultingParamName>[a-z0-9_]+)\}/im.exec(lastLine);
3132
+ if (!match || match.groups === undefined || match.groups.resultingParamName === undefined) {
3133
+ throw new PromptbookSyntaxError(spaceTrim$1(function (block) { return "\n Invalid template - each section must end with \"-> {...}\"\n\n Invalid section:\n ".concat(block(
3134
+ // TODO: Show code of invalid sections each time + DRY
3135
+ section.content
3136
+ .split('\n')
3137
+ .map(function (line) { return "> ".concat(line); })
3138
+ .join('\n')), "\n "); }));
3139
+ }
3140
+ var resultingParameterName = match.groups.resultingParamName;
3141
+ // TODO: [1] DRY description
3142
+ var description_1 = section.content;
3143
+ // Note: Remove codeblocks
3144
+ description_1 = description_1.split(/^```.*^```/gms).join('');
3145
+ //Note: Remove lists and return statement
3146
+ description_1 = description_1.split(/^(?:(?:-)|(?:\d\))|(?:`?->))\s+.*$/gm).join('');
3147
+ description_1 = spaceTrim$1(description_1);
3148
+ if (description_1 === '') {
3149
+ description_1 = undefined;
3150
+ }
3151
+ if (Object.keys(jokers).length === 0) {
3152
+ jokers = undefined;
3153
+ }
3154
+ if (Object.keys(expectAmount).length === 0) {
3155
+ expectAmount = undefined;
3156
+ }
3157
+ if (Object.keys(postprocessing).length === 0) {
3158
+ postprocessing = undefined;
3159
+ }
3160
+ dependentParameterNames = union(dependentParameterNames, extractParametersFromPromptTemplate(__assign(__assign({}, section), { description: description_1, executionType: executionType, content: content })));
3161
+ if (templateModelRequirements.modelVariant === undefined) {
3162
+ templateModelRequirements.modelVariant = 'CHAT';
3163
+ }
3164
+ var template = {
3165
+ name: titleToName(section.title),
3166
+ title: section.title,
3167
+ description: description_1,
3168
+ dependentParameterNames: Array.from(dependentParameterNames),
3169
+ executionType: executionType,
3170
+ jokers: jokers,
3171
+ postprocessing: postprocessing,
3172
+ expectations: expectAmount,
3173
+ expectFormat: expectFormat,
3174
+ modelRequirements: templateModelRequirements,
3175
+ contentLanguage: executionType === 'SCRIPT' ? language : undefined,
3176
+ content: content,
3177
+ resultingParameterName: resultingParameterName,
3178
+ };
3179
+ if (executionType !== 'PROMPT_TEMPLATE') {
3180
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
3181
+ delete template.modelRequirements;
3182
+ }
3183
+ promptbookJson.promptTemplates.push(template);
3184
+ };
3185
+ try {
3186
+ for (var _c = __values(markdownStructure.sections), _d = _c.next(); !_d.done; _d = _c.next()) {
3187
+ var section = _d.value;
3188
+ _loop_1(section);
3189
+ }
3190
+ }
3191
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
3192
+ finally {
3193
+ try {
3194
+ if (_d && !_d.done && (_b = _c.return)) _b.call(_c);
3195
+ }
3196
+ finally { if (e_2) throw e_2.error; }
3197
+ }
3198
+ // =============================================================
3199
+ return promptbookJson;
3200
+ }
3201
+ /**
3202
+ * TODO: Report here line/column of error
3203
+ * TODO: Use spaceTrim more effectively
3204
+ * TODO: [🧠] Parameter flags - isInput, isOutput, isInternal
3205
+ */
3206
+
2941
3207
  /**
2942
3208
  * Compile promptbook from string (markdown) format to JSON format
2943
3209
  *
3210
+ * Note: There are two similar functions:
3211
+ * - `promptbookStringToJson` **(preferred)** - which propperly compiles the promptbook and use embedding for external knowledge
3212
+ * - `promptbookStringToJsonSync` - use only if you need to compile promptbook synchronously and it contains NO external knowledge
3213
+ *
2944
3214
  * @param promptbookString {Promptbook} in string markdown format (.ptbk.md)
2945
3215
  * @param options - Options and tools for the compilation
2946
3216
  * @returns {Promptbook} compiled in JSON format (.ptbk.json)
@@ -2952,267 +3222,28 @@ function titleToName(value) {
2952
3222
  function promptbookStringToJson(promptbookString, options) {
2953
3223
  if (options === void 0) { options = {}; }
2954
3224
  return __awaiter(this, void 0, void 0, function () {
2955
- var llmTools, promptbookJson, knowledge, addParam, markdownStructure, markdownStructureDeepness, description, defaultModelRequirements, listItems, listItems_1, listItems_1_1, listItem, command, _loop_1, _a, _b, section;
2956
- var e_1, _c, e_2, _d;
2957
- return __generator(this, function (_e) {
2958
- switch (_e.label) {
3225
+ var llmTools, knowledge, promptbookJson;
3226
+ return __generator(this, function (_a) {
3227
+ switch (_a.label) {
2959
3228
  case 0:
2960
3229
  llmTools = options.llmTools;
2961
- promptbookJson = {
2962
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
2963
- title: undefined /* <- Note: Putting here placeholder to keep `title` on top at final JSON */,
2964
- promptbookUrl: undefined /* <- Note: Putting here placeholder to keep `promptbookUrl` on top at final JSON */,
2965
- promptbookVersion: PROMPTBOOK_VERSION,
2966
- description: undefined /* <- Note: Putting here placeholder to keep `description` on top at final JSON */,
2967
- parameters: [],
2968
- promptTemplates: [],
2969
- knowledge: [],
2970
- };
2971
3230
  if (!llmTools) return [3 /*break*/, 2];
2972
3231
  return [4 /*yield*/, prepareKnowledgeFromMarkdown({
2973
3232
  content: 'Roses are red, violets are blue, programmers use Promptbook, users too',
2974
3233
  llmTools: llmTools,
2975
3234
  })];
2976
3235
  case 1:
2977
- knowledge = _e.sent();
3236
+ knowledge = _a.sent();
2978
3237
  console.info('!!!! knowledge', knowledge);
2979
- _e.label = 2;
3238
+ _a.label = 2;
2980
3239
  case 2:
2981
- // =============================================================
2982
- // Note: 1️⃣ Normalization of the PROMPTBOOK string
2983
- promptbookString = removeContentComments(promptbookString);
2984
- promptbookString = promptbookString.replaceAll(/`\{(?<parameterName>[a-z0-9_]+)\}`/gi, '{$<parameterName>}');
2985
- promptbookString = promptbookString.replaceAll(/`->\s+\{(?<parameterName>[a-z0-9_]+)\}`/gi, '-> {$<parameterName>}');
2986
- addParam = function (parameterCommand) {
2987
- var parameterName = parameterCommand.parameterName, parameterDescription = parameterCommand.parameterDescription, isInput = parameterCommand.isInput, isOutput = parameterCommand.isOutput;
2988
- var existingParameter = promptbookJson.parameters.find(function (parameter) { return parameter.name === parameterName; });
2989
- if (existingParameter &&
2990
- existingParameter.description &&
2991
- existingParameter.description !== parameterDescription &&
2992
- parameterDescription) {
2993
- throw new PromptbookSyntaxError(spaceTrim$1(function (block) { return "\n Parameter {".concat(parameterName, "} is defined multiple times with different description.\n\n First definition:\n ").concat(block(existingParameter.description || '[undefined]'), "\n\n Second definition:\n ").concat(block(parameterDescription || '[undefined]'), "\n "); }));
2994
- }
2995
- if (existingParameter) {
2996
- if (parameterDescription) {
2997
- existingParameter.description = parameterDescription;
2998
- }
2999
- }
3000
- else {
3001
- promptbookJson.parameters.push({
3002
- name: parameterName,
3003
- description: parameterDescription || undefined,
3004
- isInput: isInput,
3005
- isOutput: isOutput,
3006
- });
3007
- }
3008
- };
3009
- markdownStructure = markdownToMarkdownStructure(promptbookString);
3010
- markdownStructureDeepness = countMarkdownStructureDeepness(markdownStructure);
3011
- if (markdownStructureDeepness !== 2) {
3012
- throw new PromptbookSyntaxError(spaceTrim$1("\n Invalid markdown structure.\n The markdown must have exactly 2 levels of headings (one top-level section and one section for each template).\n Now it has ".concat(markdownStructureDeepness, " levels of headings.\n ")));
3013
- }
3014
- promptbookJson.title = markdownStructure.title;
3015
- description = markdownStructure.content;
3016
- // Note: Remove codeblocks
3017
- description = description.split(/^```.*^```/gms).join('');
3018
- //Note: Remove lists and return statement
3019
- description = description.split(/^(?:(?:-)|(?:\d\))|(?:`?->))\s+.*$/gm).join('');
3020
- description = spaceTrim$1(description);
3021
- if (description === '') {
3022
- description = undefined;
3023
- }
3024
- promptbookJson.description = description;
3025
- defaultModelRequirements = {};
3026
- listItems = extractAllListItemsFromMarkdown(markdownStructure.content);
3027
- try {
3028
- for (listItems_1 = __values(listItems), listItems_1_1 = listItems_1.next(); !listItems_1_1.done; listItems_1_1 = listItems_1.next()) {
3029
- listItem = listItems_1_1.value;
3030
- command = parseCommand(listItem);
3031
- switch (command.type) {
3032
- case 'PROMPTBOOK_URL':
3033
- promptbookJson.promptbookUrl = command.promptbookUrl.href;
3034
- break;
3035
- case 'PROMPTBOOK_VERSION':
3036
- promptbookJson.promptbookVersion = command.promptbookVersion;
3037
- break;
3038
- case 'MODEL':
3039
- defaultModelRequirements[command.key] = command.value;
3040
- break;
3041
- case 'PARAMETER':
3042
- addParam(command);
3043
- break;
3044
- default:
3045
- throw new PromptbookSyntaxError("Command ".concat(command.type, " is not allowed in the head of the promptbook ONLY at the prompt template block"));
3046
- }
3047
- }
3048
- }
3049
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
3050
- finally {
3051
- try {
3052
- if (listItems_1_1 && !listItems_1_1.done && (_c = listItems_1.return)) _c.call(listItems_1);
3053
- }
3054
- finally { if (e_1) throw e_1.error; }
3055
- }
3056
- _loop_1 = function (section) {
3057
- var e_3, _f;
3058
- // TODO: Parse prompt template description (the content out of the codeblock and lists)
3059
- var templateModelRequirements = __assign({}, defaultModelRequirements);
3060
- var listItems_3 = extractAllListItemsFromMarkdown(section.content);
3061
- var dependentParameterNames = new Set();
3062
- var executionType = 'PROMPT_TEMPLATE';
3063
- var jokers = [];
3064
- var postprocessing = [];
3065
- var expectAmount = {};
3066
- var expectFormat = undefined;
3067
- var isExecutionTypeChanged = false;
3068
- try {
3069
- for (var listItems_2 = (e_3 = void 0, __values(listItems_3)), listItems_2_1 = listItems_2.next(); !listItems_2_1.done; listItems_2_1 = listItems_2.next()) {
3070
- var listItem = listItems_2_1.value;
3071
- var command = parseCommand(listItem);
3072
- switch (command.type) {
3073
- case 'JOKER':
3074
- jokers.push(command.parameterName);
3075
- dependentParameterNames.add(command.parameterName);
3076
- break;
3077
- case 'EXECUTE':
3078
- if (isExecutionTypeChanged) {
3079
- throw new PromptbookSyntaxError('Execution type is already defined in the prompt template. It can be defined only once.');
3080
- }
3081
- executionType = command.executionType;
3082
- isExecutionTypeChanged = true;
3083
- break;
3084
- case 'MODEL':
3085
- templateModelRequirements[command.key] = command.value;
3086
- break;
3087
- case 'PARAMETER':
3088
- // Note: This is just for detecting resulitng parameter name
3089
- addParam(command);
3090
- break;
3091
- case 'POSTPROCESS':
3092
- postprocessing.push(command.functionName);
3093
- break;
3094
- case 'EXPECT_AMOUNT':
3095
- // eslint-disable-next-line no-case-declarations
3096
- var unit = command.unit.toLowerCase();
3097
- expectAmount[unit] = expectAmount[unit] || {};
3098
- if (command.sign === 'MINIMUM' || command.sign === 'EXACTLY') {
3099
- if (expectAmount[unit].min !== undefined) {
3100
- throw new PromptbookSyntaxError("Already defined minumum ".concat(expectAmount[unit].min, " ").concat(command.unit.toLowerCase(), ", now trying to redefine it to ").concat(command.amount));
3101
- }
3102
- expectAmount[unit].min = command.amount;
3103
- } /* not else */
3104
- if (command.sign === 'MAXIMUM' || command.sign === 'EXACTLY') {
3105
- if (expectAmount[unit].max !== undefined) {
3106
- throw new PromptbookSyntaxError("Already defined maximum ".concat(expectAmount[unit].max, " ").concat(command.unit.toLowerCase(), ", now trying to redefine it to ").concat(command.amount));
3107
- }
3108
- expectAmount[unit].max = command.amount;
3109
- }
3110
- break;
3111
- case 'EXPECT_FORMAT':
3112
- if (expectFormat !== undefined && command.format !== expectFormat) {
3113
- throw new PromptbookSyntaxError("Expect format is already defined to \"".concat(expectFormat, "\". Now you try to redefine it by \"").concat(command.format, "\"."));
3114
- }
3115
- expectFormat = command.format;
3116
- break;
3117
- default:
3118
- throw new PromptbookSyntaxError("Command ".concat(command.type, " is not allowed in the block of the prompt template ONLY at the head of the promptbook"));
3119
- }
3120
- }
3121
- }
3122
- catch (e_3_1) { e_3 = { error: e_3_1 }; }
3123
- finally {
3124
- try {
3125
- if (listItems_2_1 && !listItems_2_1.done && (_f = listItems_2.return)) _f.call(listItems_2);
3126
- }
3127
- finally { if (e_3) throw e_3.error; }
3128
- }
3129
- var _g = extractOneBlockFromMarkdown(section.content), language = _g.language, content = _g.content;
3130
- if (executionType === 'SCRIPT') {
3131
- if (!language) {
3132
- throw new PromptbookSyntaxError('You must specify the language of the script in the prompt template');
3133
- }
3134
- else if (!SUPPORTED_SCRIPT_LANGUAGES.includes(language)) {
3135
- throw new PromptbookSyntaxError(spaceTrim$1(function (block) { return "\n Script language ".concat(language, " is not supported.\n\n Supported languages are:\n ").concat(block(SUPPORTED_SCRIPT_LANGUAGES.join(', ')), "\n\n "); }));
3136
- }
3137
- }
3138
- var lastLine = section.content.split('\n').pop();
3139
- var match = /^->\s*\{(?<resultingParamName>[a-z0-9_]+)\}/im.exec(lastLine);
3140
- if (!match || match.groups === undefined || match.groups.resultingParamName === undefined) {
3141
- throw new PromptbookSyntaxError(spaceTrim$1(function (block) { return "\n Invalid template - each section must end with \"-> {...}\"\n\n Invalid section:\n ".concat(block(
3142
- // TODO: Show code of invalid sections each time + DRY
3143
- section.content
3144
- .split('\n')
3145
- .map(function (line) { return "> ".concat(line); })
3146
- .join('\n')), "\n "); }));
3147
- }
3148
- var resultingParameterName = match.groups.resultingParamName;
3149
- // TODO: [1] DRY description
3150
- var description_1 = section.content;
3151
- // Note: Remove codeblocks
3152
- description_1 = description_1.split(/^```.*^```/gms).join('');
3153
- //Note: Remove lists and return statement
3154
- description_1 = description_1.split(/^(?:(?:-)|(?:\d\))|(?:`?->))\s+.*$/gm).join('');
3155
- description_1 = spaceTrim$1(description_1);
3156
- if (description_1 === '') {
3157
- description_1 = undefined;
3158
- }
3159
- if (Object.keys(jokers).length === 0) {
3160
- jokers = undefined;
3161
- }
3162
- if (Object.keys(expectAmount).length === 0) {
3163
- expectAmount = undefined;
3164
- }
3165
- if (Object.keys(postprocessing).length === 0) {
3166
- postprocessing = undefined;
3167
- }
3168
- dependentParameterNames = union(dependentParameterNames, extractParametersFromPromptTemplate(__assign(__assign({}, section), { description: description_1, executionType: executionType, content: content })));
3169
- if (templateModelRequirements.modelVariant === undefined) {
3170
- templateModelRequirements.modelVariant = 'CHAT';
3171
- }
3172
- var template = {
3173
- name: titleToName(section.title),
3174
- title: section.title,
3175
- description: description_1,
3176
- dependentParameterNames: Array.from(dependentParameterNames),
3177
- executionType: executionType,
3178
- jokers: jokers,
3179
- postprocessing: postprocessing,
3180
- expectations: expectAmount,
3181
- expectFormat: expectFormat,
3182
- modelRequirements: templateModelRequirements,
3183
- contentLanguage: executionType === 'SCRIPT' ? language : undefined,
3184
- content: content,
3185
- resultingParameterName: resultingParameterName,
3186
- };
3187
- if (executionType !== 'PROMPT_TEMPLATE') {
3188
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
3189
- delete template.modelRequirements;
3190
- }
3191
- promptbookJson.promptTemplates.push(template);
3192
- };
3193
- try {
3194
- for (_a = __values(markdownStructure.sections), _b = _a.next(); !_b.done; _b = _a.next()) {
3195
- section = _b.value;
3196
- _loop_1(section);
3197
- }
3198
- }
3199
- catch (e_2_1) { e_2 = { error: e_2_1 }; }
3200
- finally {
3201
- try {
3202
- if (_b && !_b.done && (_d = _a.return)) _d.call(_a);
3203
- }
3204
- finally { if (e_2) throw e_2.error; }
3205
- }
3206
- // =============================================================
3240
+ promptbookJson = promptbookStringToJsonSync(promptbookString);
3207
3241
  return [2 /*return*/, promptbookJson];
3208
3242
  }
3209
3243
  });
3210
3244
  });
3211
3245
  }
3212
3246
  /**
3213
- * TODO: Report here line/column of error
3214
- * TODO: Use spaceTrim more effectively
3215
- * TODO: [🧠] Parameter flags - isInput, isOutput, isInternal
3216
3247
  * TODO: [🏏] Leverage the batch API and build queues @see https://platform.openai.com/docs/guides/batch
3217
3248
  */
3218
3249
 
@@ -3567,9 +3598,10 @@ function initializeMake(program) {
3567
3598
  helloCommand.option('--no-validation', "Do not validate logic of promptbooks in library", true);
3568
3599
  helloCommand.option('--validation', "Types of validations separated by comma (options \"logic\",\"imports\")", 'logic,imports');
3569
3600
  helloCommand.option('--verbose', "Is verbose", false);
3601
+ helloCommand.option('-o, --out-file', spaceTrim("\n Where to save the builded library\n\n Note: If you keep it \"".concat(PROMPTBOOK_MAKED_BASE_FILENAME, "\" it will be saved in the root of the promptbook directory\n If you set it to a path, it will be saved in that path\n BUT you can use only one format and set correct extension\n ")), PROMPTBOOK_MAKED_BASE_FILENAME);
3570
3602
  // TODO: !!! Auto-detect AI api keys + explicit api keys as argv
3571
3603
  helloCommand.action(function (path, _a) {
3572
- var projectName = _a.projectName, format = _a.format, validation = _a.validation, verbose = _a.verbose;
3604
+ var projectName = _a.projectName, format = _a.format, validation = _a.validation, verbose = _a.verbose, outFile = _a.outFile;
3573
3605
  return __awaiter(_this, void 0, void 0, function () {
3574
3606
  var formats, validations, library, validations_1, validations_1_1, validation_1, _b, _c, promptbookUrl, promptbook, e_1_1, e_2_1, libraryJson, libraryJsonString, saveFile;
3575
3607
  var e_2, _d, e_1, _e;
@@ -3577,7 +3609,7 @@ function initializeMake(program) {
3577
3609
  return __generator(this, function (_f) {
3578
3610
  switch (_f.label) {
3579
3611
  case 0:
3580
- console.info('!!!', { projectName: projectName, path: path, format: format, validation: validation, verbose: verbose });
3612
+ console.info('!!!', { projectName: projectName, path: path, format: format, validation: validation, verbose: verbose, outFile: outFile });
3581
3613
  formats = (format || '')
3582
3614
  .split(',')
3583
3615
  .map(function (_) { return _.trim(); })
@@ -3586,6 +3618,9 @@ function initializeMake(program) {
3586
3618
  .split(',')
3587
3619
  .map(function (_) { return _.trim(); })
3588
3620
  .filter(function (_) { return _ !== ''; });
3621
+ if (outFile !== PROMPTBOOK_MAKED_BASE_FILENAME && formats.length !== 1) {
3622
+ throw new Error("You can use only one format when saving to a file");
3623
+ }
3589
3624
  return [4 /*yield*/, createLibraryFromDirectory(path, {
3590
3625
  isVerbose: verbose,
3591
3626
  isRecursive: true,
@@ -3658,7 +3693,12 @@ function initializeMake(program) {
3658
3693
  return __generator(this, function (_a) {
3659
3694
  switch (_a.label) {
3660
3695
  case 0:
3661
- filePath = join(path, "".concat(PROMPTBOOK_MAKED_BASE_FILENAME, ".").concat(extension));
3696
+ filePath = outFile !== PROMPTBOOK_MAKED_BASE_FILENAME
3697
+ ? outFile
3698
+ : join(path, "".concat(PROMPTBOOK_MAKED_BASE_FILENAME, ".").concat(extension));
3699
+ if (!outFile.endsWith(".".concat(extension))) {
3700
+ console.warn(colors.yellow("Warning: Extension of output file should be \"".concat(extension, "\"")));
3701
+ }
3662
3702
  return [4 /*yield*/, writeFile(filePath, content, 'utf-8')];
3663
3703
  case 1:
3664
3704
  _a.sent();