@promptbook/node 0.63.4 → 0.65.0-0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (24) hide show
  1. package/esm/index.es.js +460 -94
  2. package/esm/index.es.js.map +1 -1
  3. package/esm/typings/promptbook-collection/index.d.ts +9 -171
  4. package/esm/typings/src/_packages/node.index.d.ts +6 -0
  5. package/esm/typings/src/_packages/types.index.d.ts +4 -2
  6. package/esm/typings/src/commands/KNOWLEDGE/KnowledgeCommand.d.ts +2 -2
  7. package/esm/typings/src/llm-providers/_common/LlmToolsConfiguration.d.ts +28 -0
  8. package/esm/typings/src/llm-providers/_common/config.d.ts +15 -0
  9. package/esm/typings/src/llm-providers/_common/createLlmToolsFromConfiguration.d.ts +32 -0
  10. package/esm/typings/src/llm-providers/_common/createLlmToolsFromConfigurationFromEnv.d.ts +23 -0
  11. package/esm/typings/src/llm-providers/_common/createLlmToolsFromEnv.d.ts +7 -22
  12. package/esm/typings/src/llm-providers/_common/getLlmToolsForCli.d.ts +1 -0
  13. package/esm/typings/src/llm-providers/_common/getLlmToolsForTestingAndScriptsAndPlayground.d.ts +3 -2
  14. package/esm/typings/src/llm-providers/anthropic-claude/AnthropicClaudeExecutionTools.d.ts +1 -0
  15. package/esm/typings/src/llm-providers/azure-openai/AzureOpenAiExecutionTools.d.ts +1 -0
  16. package/esm/typings/src/llm-providers/openai/OpenAiExecutionTools.d.ts +1 -0
  17. package/esm/typings/src/llm-providers/remote/RemoteLlmExecutionTools.d.ts +1 -0
  18. package/esm/typings/src/prepare/preparePipeline.d.ts +1 -0
  19. package/esm/typings/src/types/PipelineJson/KnowledgeSourceJson.d.ts +8 -2
  20. package/esm/typings/src/types/typeAliases.d.ts +2 -2
  21. package/esm/typings/src/utils/organization/TODO_string.d.ts +6 -0
  22. package/package.json +3 -2
  23. package/umd/index.umd.js +465 -97
  24. package/umd/index.umd.js.map +1 -1
package/umd/index.umd.js CHANGED
@@ -1,8 +1,8 @@
1
1
  (function (global, factory) {
2
- typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('colors'), require('fs/promises'), require('path'), require('spacetrim'), require('prettier'), require('prettier/parser-html'), require('path/posix'), require('dotenv'), require('@anthropic-ai/sdk'), require('openai'), require('crypto-js/enc-hex'), require('crypto-js/sha256')) :
3
- typeof define === 'function' && define.amd ? define(['exports', 'colors', 'fs/promises', 'path', 'spacetrim', 'prettier', 'prettier/parser-html', 'path/posix', 'dotenv', '@anthropic-ai/sdk', 'openai', 'crypto-js/enc-hex', 'crypto-js/sha256'], factory) :
4
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global["promptbook-node"] = {}, global.colors, global.promises, global.path, global.spaceTrim, global.prettier, global.parserHtml, global.posix, global.dotenv, global.Anthropic, global.OpenAI, global.hexEncoder, global.sha256));
5
- })(this, (function (exports, colors, promises, path, spaceTrim, prettier, parserHtml, posix, dotenv, Anthropic, OpenAI, hexEncoder, sha256) { 'use strict';
2
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('colors'), require('fs/promises'), require('path'), require('spacetrim'), require('prettier'), require('prettier/parser-html'), require('crypto-js/enc-hex'), require('crypto-js/sha256'), require('path/posix'), require('@anthropic-ai/sdk'), require('@azure/openai'), require('openai'), require('dotenv')) :
3
+ typeof define === 'function' && define.amd ? define(['exports', 'colors', 'fs/promises', 'path', 'spacetrim', 'prettier', 'prettier/parser-html', 'crypto-js/enc-hex', 'crypto-js/sha256', 'path/posix', '@anthropic-ai/sdk', '@azure/openai', 'openai', 'dotenv'], factory) :
4
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global["promptbook-node"] = {}, global.colors, global.promises, global.path, global.spaceTrim, global.prettier, global.parserHtml, global.hexEncoder, global.sha256, global.posix, global.Anthropic, global.openai, global.OpenAI, global.dotenv));
5
+ })(this, (function (exports, colors, promises, path, spaceTrim, prettier, parserHtml, hexEncoder, sha256, posix, Anthropic, openai, OpenAI, dotenv) { 'use strict';
6
6
 
7
7
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
8
8
 
@@ -27,17 +27,17 @@
27
27
  var colors__default = /*#__PURE__*/_interopDefaultLegacy(colors);
28
28
  var spaceTrim__default = /*#__PURE__*/_interopDefaultLegacy(spaceTrim);
29
29
  var parserHtml__default = /*#__PURE__*/_interopDefaultLegacy(parserHtml);
30
- var dotenv__namespace = /*#__PURE__*/_interopNamespace(dotenv);
31
- var Anthropic__default = /*#__PURE__*/_interopDefaultLegacy(Anthropic);
32
- var OpenAI__default = /*#__PURE__*/_interopDefaultLegacy(OpenAI);
33
30
  var hexEncoder__default = /*#__PURE__*/_interopDefaultLegacy(hexEncoder);
34
31
  var sha256__default = /*#__PURE__*/_interopDefaultLegacy(sha256);
32
+ var Anthropic__default = /*#__PURE__*/_interopDefaultLegacy(Anthropic);
33
+ var OpenAI__default = /*#__PURE__*/_interopDefaultLegacy(OpenAI);
34
+ var dotenv__namespace = /*#__PURE__*/_interopNamespace(dotenv);
35
35
 
36
36
  // ⚠️ WARNING: This code has been generated so that any manual changes will be overwritten
37
37
  /**
38
38
  * The version of the Promptbook library
39
39
  */
40
- var PROMPTBOOK_VERSION = '0.63.3';
40
+ var PROMPTBOOK_VERSION = '0.64.0-0';
41
41
  // TODO: !!!! List here all the versions and annotate + put into script
42
42
 
43
43
  /*! *****************************************************************************
@@ -412,7 +412,7 @@
412
412
  else if (blockType === 'PROMPT_DIALOG') {
413
413
  commands_1.push("PROMPT DIALOG");
414
414
  // Note: Nothing special here
415
- } // <- }else if([🩻]
415
+ } // <- }else if([🅱]
416
416
  if (jokers) {
417
417
  try {
418
418
  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()) {
@@ -712,7 +712,7 @@
712
712
  });
713
713
  }
714
714
 
715
- var PipelineCollection = [{pipelineUrl:"https://promptbook.studio/promptbook/prepare-knowledge-from-markdown.ptbk.md",sourceFile:"./promptbook-collection/prepare-knowledge-from-markdown.ptbk.md",title:"Prepare Knowledge from Markdown",promptbookVersion:"0.63.3",parameters:[{name:"knowledgeContent",description:"Markdown document content",isInput:true,isOutput:false},{name:"knowledgePieces",description:"The knowledge JSON object",isInput:false,isOutput:true}],promptTemplates:[{blockType:"PROMPT_TEMPLATE",name:"knowledge",title:"Knowledge",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> {knowledgeContent}",dependentParameterNames:["knowledgeContent"],resultingParameterName:"knowledgePieces"}],knowledgeSources:[],knowledgePieces:[],personas:[],preparations:[{id:1,promptbookVersion:"0.63.3",usage:{price:{value:0},input:{tokensCount:{value:0},charactersCount:{value:0},wordsCount:{value:0},sentencesCount:{value:0},linesCount:{value:0},paragraphsCount:{value:0},pagesCount:{value:0}},output:{tokensCount:{value:0},charactersCount:{value:0},wordsCount:{value:0},sentencesCount:{value:0},linesCount:{value:0},paragraphsCount:{value:0},pagesCount:{value:0}}}}]},{pipelineUrl:"https://promptbook.studio/promptbook/prepare-knowledge-keywords.ptbk.md",sourceFile:"./promptbook-collection/prepare-knowledge-keywords.ptbk.md",title:"Prepare Keywords",promptbookVersion:"0.63.3",parameters:[{name:"knowledgePieceContent",description:"The content",isInput:true,isOutput:false},{name:"keywords",description:"Keywords separated by comma",isInput:false,isOutput:true}],promptTemplates:[{blockType:"PROMPT_TEMPLATE",name:"knowledge",title:"Knowledge",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> {knowledgePieceContent}",dependentParameterNames:["knowledgePieceContent"],resultingParameterName:"keywords"}],knowledgeSources:[],knowledgePieces:[],personas:[],preparations:[{id:1,promptbookVersion:"0.63.3",usage:{price:{value:0},input:{tokensCount:{value:0},charactersCount:{value:0},wordsCount:{value:0},sentencesCount:{value:0},linesCount:{value:0},paragraphsCount:{value:0},pagesCount:{value:0}},output:{tokensCount:{value:0},charactersCount:{value:0},wordsCount:{value:0},sentencesCount:{value:0},linesCount:{value:0},paragraphsCount:{value:0},pagesCount:{value:0}}}}]},{pipelineUrl:"https://promptbook.studio/promptbook/prepare-knowledge-title.ptbk.md",sourceFile:"./promptbook-collection/prepare-knowledge-title.ptbk.md",title:"Prepare Title",promptbookVersion:"0.63.3",parameters:[{name:"knowledgePieceContent",description:"The content",isInput:true,isOutput:false},{name:"title",description:"The title of the document",isInput:false,isOutput:true}],promptTemplates:[{blockType:"PROMPT_TEMPLATE",name:"knowledge",title:"Knowledge",modelRequirements:{modelVariant:"CHAT",modelName:"claude-3-opus-20240229"},content:"You are experienced content creator, write best title for the document.\n\n# Rules\n\n- Write just title, nothing else\n- Title should be concise and clear\n- Write maximum 5 words for the title\n\n# The document\n\n> {knowledgePieceContent}",expectations:{words:{min:1,max:8}},dependentParameterNames:["knowledgePieceContent"],resultingParameterName:"title"}],knowledgeSources:[],knowledgePieces:[],personas:[],preparations:[{id:1,promptbookVersion:"0.63.3",usage:{price:{value:0},input:{tokensCount:{value:0},charactersCount:{value:0},wordsCount:{value:0},sentencesCount:{value:0},linesCount:{value:0},paragraphsCount:{value:0},pagesCount:{value:0}},output:{tokensCount:{value:0},charactersCount:{value:0},wordsCount:{value:0},sentencesCount:{value:0},linesCount:{value:0},paragraphsCount:{value:0},pagesCount:{value:0}}}}]},{pipelineUrl:"https://promptbook.studio/promptbook/prepare-persona.ptbk.md",sourceFile:"./promptbook-collection/prepare-persona.ptbk.md",title:"Prepare Keywords",promptbookVersion:"0.63.3",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}],promptTemplates:[{blockType:"PROMPT_TEMPLATE",name:"make-model-requirements",title:"Make modelRequirements",modelRequirements:{modelVariant:"CHAT",modelName:"gpt-4-turbo"},content:"You are experienced AI engineer, you need to create virtual assistant.\nWrite\n\n## Sample\n\n```json\n{\n\"modelName\": \"gpt-4o\",\n\"systemMessage\": \"You are experienced AI engineer and helpfull assistant.\",\n\"temperature\": 0.7\n}\n```\n\n## Instructions\n\n### Option `modelName`\n\nPick from the following models:\n\n- {availableModelNames}\n\n### Option `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### Option `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}",expectFormat:"JSON",dependentParameterNames:["availableModelNames","personaDescription"],resultingParameterName:"modelRequirements"}],knowledgeSources:[],knowledgePieces:[],personas:[],preparations:[{id:1,promptbookVersion:"0.63.3",usage:{price:{value:0},input:{tokensCount:{value:0},charactersCount:{value:0},wordsCount:{value:0},sentencesCount:{value:0},linesCount:{value:0},paragraphsCount:{value:0},pagesCount:{value:0}},output:{tokensCount:{value:0},charactersCount:{value:0},wordsCount:{value:0},sentencesCount:{value:0},linesCount:{value:0},paragraphsCount:{value:0},pagesCount:{value:0}}}}]}];
715
+ var PipelineCollection = [{title:"Prepare Knowledge from Markdown",pipelineUrl:"https://promptbook.studio/promptbook/prepare-knowledge-from-markdown.ptbk.md",promptbookVersion:"0.64.0-0",parameters:[{name:"knowledgeContent",description:"Markdown document content",isInput:true,isOutput:false},{name:"knowledgePieces",description:"The knowledge JSON object",isInput:false,isOutput:true}],promptTemplates:[{blockType:"PROMPT_TEMPLATE",name:"knowledge",title:"Knowledge",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> {knowledgeContent}",dependentParameterNames:["knowledgeContent"],resultingParameterName:"knowledgePieces"}],knowledgeSources:[],knowledgePieces:[],personas:[],preparations:[],sourceFile:"./promptbook-collection/prepare-knowledge-from-markdown.ptbk.md"},{title:"Prepare Keywords",pipelineUrl:"https://promptbook.studio/promptbook/prepare-knowledge-keywords.ptbk.md",promptbookVersion:"0.64.0-0",parameters:[{name:"knowledgePieceContent",description:"The content",isInput:true,isOutput:false},{name:"keywords",description:"Keywords separated by comma",isInput:false,isOutput:true}],promptTemplates:[{blockType:"PROMPT_TEMPLATE",name:"knowledge",title:"Knowledge",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> {knowledgePieceContent}",dependentParameterNames:["knowledgePieceContent"],resultingParameterName:"keywords"}],knowledgeSources:[],knowledgePieces:[],personas:[],preparations:[],sourceFile:"./promptbook-collection/prepare-knowledge-keywords.ptbk.md"},{title:"Prepare Title",pipelineUrl:"https://promptbook.studio/promptbook/prepare-knowledge-title.ptbk.md",promptbookVersion:"0.64.0-0",parameters:[{name:"knowledgePieceContent",description:"The content",isInput:true,isOutput:false},{name:"title",description:"The title of the document",isInput:false,isOutput:true}],promptTemplates:[{blockType:"PROMPT_TEMPLATE",name:"knowledge",title:"Knowledge",modelRequirements:{modelVariant:"CHAT",modelName:"claude-3-opus-20240229"},content:"You are experienced content creator, write best title for the document.\n\n# Rules\n\n- Write just title, nothing else\n- Title should be concise and clear\n- Write maximum 5 words for the title\n\n# The document\n\n> {knowledgePieceContent}",expectations:{words:{min:1,max:8}},dependentParameterNames:["knowledgePieceContent"],resultingParameterName:"title"}],knowledgeSources:[],knowledgePieces:[],personas:[],preparations:[],sourceFile:"./promptbook-collection/prepare-knowledge-title.ptbk.md"},{title:"Prepare Keywords",pipelineUrl:"https://promptbook.studio/promptbook/prepare-persona.ptbk.md",promptbookVersion:"0.64.0-0",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}],promptTemplates:[{blockType:"PROMPT_TEMPLATE",name:"make-model-requirements",title:"Make modelRequirements",modelRequirements:{modelVariant:"CHAT",modelName:"gpt-4-turbo"},content:"You are experienced AI engineer, you need to create virtual assistant.\nWrite\n\n## Sample\n\n```json\n{\n\"modelName\": \"gpt-4o\",\n\"systemMessage\": \"You are experienced AI engineer and helpfull assistant.\",\n\"temperature\": 0.7\n}\n```\n\n## Instructions\n\n### Option `modelName`\n\nPick from the following models:\n\n- {availableModelNames}\n\n### Option `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### Option `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}",expectFormat:"JSON",dependentParameterNames:["availableModelNames","personaDescription"],resultingParameterName:"modelRequirements"}],knowledgeSources:[],knowledgePieces:[],personas:[],preparations:[],sourceFile:"./promptbook-collection/prepare-persona.ptbk.md"}];
716
716
 
717
717
  /**
718
718
  * This error indicates that the promptbook in a markdown format cannot be parsed into a valid promptbook object
@@ -1279,7 +1279,7 @@
1279
1279
  pipelineJsonToString(unpreparePipeline(pipeline)) !==
1280
1280
  pipelineJsonToString(unpreparePipeline(this.collection.get(pipeline.pipelineUrl)))) {
1281
1281
  var existing = this.collection.get(pipeline.pipelineUrl);
1282
- throw new ReferenceError$1(spaceTrim.spaceTrim("\n Pipeline with URL \"".concat(pipeline.pipelineUrl, "\" is already in the collection\n\n Conflicting files:\n ").concat(existing.sourceFile || 'Unknown', "\n ").concat(pipeline.sourceFile || 'Unknown', "\n\n Note: Pipelines with the same URL are not allowed\n Only exepction is when the pipelines are identical\n\n ")));
1282
+ throw new ReferenceError$1(spaceTrim.spaceTrim("\n Pipeline with URL \"".concat(pipeline.pipelineUrl, "\" is already in the collection \uD83C\uDF4E\n\n Conflicting files:\n ").concat(existing.sourceFile || 'Unknown', "\n ").concat(pipeline.sourceFile || 'Unknown', "\n\n Note: You have probably forgotten to run \"ptbk make\" to update the collection\n Note: Pipelines with the same URL are not allowed\n Only exepction is when the pipelines are identical\n\n ")));
1283
1283
  }
1284
1284
  // Note: [🧠] Overwrite existing pipeline with the same URL
1285
1285
  this.collection.set(pipeline.pipelineUrl, pipeline);
@@ -3466,7 +3466,7 @@
3466
3466
  var partialPieces, pieces;
3467
3467
  return __generator(this, function (_a) {
3468
3468
  switch (_a.label) {
3469
- case 0: return [4 /*yield*/, prepareKnowledgeFromMarkdown(knowledgeSource.source, // <- TODO: [🐝] !!! Unhardcode markdown, detect which type it is - BE AWARE of big package size
3469
+ case 0: return [4 /*yield*/, prepareKnowledgeFromMarkdown(knowledgeSource.sourceContent, // <- TODO: [🐝] !!! Unhardcode markdown, detect which type it is - BE AWARE of big package size
3470
3470
  options)];
3471
3471
  case 1:
3472
3472
  partialPieces = _a.sent();
@@ -3656,6 +3656,35 @@
3656
3656
  * TODO: [🏢] !! Check validity of `temperature` in pipeline
3657
3657
  */
3658
3658
 
3659
+ /**
3660
+ * @@@
3661
+ *
3662
+ * Note: It is usefull @@@
3663
+ *
3664
+ * @param pipeline
3665
+ * @public exported from `@promptbook/utils`
3666
+ */
3667
+ function clonePipeline(pipeline) {
3668
+ // Note: Not using spread operator (...) because @@@
3669
+ var pipelineUrl = pipeline.pipelineUrl, sourceFile = pipeline.sourceFile, title = pipeline.title, promptbookVersion = pipeline.promptbookVersion, description = pipeline.description, parameters = pipeline.parameters, promptTemplates = pipeline.promptTemplates, knowledgeSources = pipeline.knowledgeSources, knowledgePieces = pipeline.knowledgePieces, personas = pipeline.personas, preparations = pipeline.preparations;
3670
+ return {
3671
+ pipelineUrl: pipelineUrl,
3672
+ sourceFile: sourceFile,
3673
+ title: title,
3674
+ promptbookVersion: promptbookVersion,
3675
+ description: description,
3676
+ parameters: parameters,
3677
+ promptTemplates: promptTemplates,
3678
+ knowledgeSources: knowledgeSources,
3679
+ knowledgePieces: knowledgePieces,
3680
+ personas: personas,
3681
+ preparations: preparations,
3682
+ };
3683
+ }
3684
+ /**
3685
+ * TODO: [🍙] Make some standart order of json properties
3686
+ */
3687
+
3659
3688
  /**
3660
3689
  * @@@
3661
3690
  *
@@ -3708,40 +3737,12 @@
3708
3737
  * TODO: [🧠][🥜]
3709
3738
  */
3710
3739
 
3711
- /**
3712
- * @@@
3713
- *
3714
- * Note: It is usefull @@@
3715
- *
3716
- * @param pipeline
3717
- * @public exported from `@promptbook/utils`
3718
- */
3719
- function clonePipeline(pipeline) {
3720
- // Note: Not using spread operator (...) because @@@
3721
- var pipelineUrl = pipeline.pipelineUrl, sourceFile = pipeline.sourceFile, title = pipeline.title, promptbookVersion = pipeline.promptbookVersion, description = pipeline.description, parameters = pipeline.parameters, promptTemplates = pipeline.promptTemplates, knowledgeSources = pipeline.knowledgeSources, knowledgePieces = pipeline.knowledgePieces, personas = pipeline.personas, preparations = pipeline.preparations;
3722
- return {
3723
- pipelineUrl: pipelineUrl,
3724
- sourceFile: sourceFile,
3725
- title: title,
3726
- promptbookVersion: promptbookVersion,
3727
- description: description,
3728
- parameters: parameters,
3729
- promptTemplates: promptTemplates,
3730
- knowledgeSources: knowledgeSources,
3731
- knowledgePieces: knowledgePieces,
3732
- personas: personas,
3733
- preparations: preparations,
3734
- };
3735
- }
3736
- /**
3737
- * TODO: [🍙] Make some standart order of json properties
3738
- */
3739
-
3740
3740
  /**
3741
3741
  * Prepare pipeline from string (markdown) format to JSON format
3742
3742
  *
3743
3743
  * Note: This function does not validate logic of the pipeline
3744
3744
  * Note: This function acts as part of compilation process
3745
+ * Note: When the pipeline is already prepared, it returns the same pipeline
3745
3746
  * @public exported from `@promptbook/core`
3746
3747
  */
3747
3748
  function preparePipeline(pipeline, options) {
@@ -3756,6 +3757,9 @@
3756
3757
  return __generator(this, function (_c) {
3757
3758
  switch (_c.label) {
3758
3759
  case 0:
3760
+ if (isPipelinePrepared(pipeline)) {
3761
+ return [2 /*return*/, pipeline];
3762
+ }
3759
3763
  llmTools = options.llmTools, _a = options.maxParallelCount, maxParallelCount = _a === void 0 ? MAX_PARALLEL_COUNT : _a, _b = options.isVerbose, isVerbose = _b === void 0 ? false : _b;
3760
3764
  parameters = pipeline.parameters, promptTemplates = pipeline.promptTemplates, knowledgeSources = pipeline.knowledgeSources, personas = pipeline.personas;
3761
3765
  llmToolsWithUsage = countTotalUsage(llmTools);
@@ -3889,34 +3893,37 @@
3889
3893
  */
3890
3894
  parse: function (input) {
3891
3895
  var args = input.args;
3892
- var source = args[0];
3893
- if (source === undefined) {
3896
+ var sourceContent = spaceTrim__default["default"](args[0] || '');
3897
+ if (sourceContent === '') {
3894
3898
  throw new ParsingError("Source is not defined");
3895
3899
  }
3896
- if (source.startsWith('http://')) {
3900
+ // TODO: !!!! Following checks should be applied every link in the `sourceContent`
3901
+ if (sourceContent.startsWith('http://')) {
3897
3902
  throw new ParsingError("Source is not secure");
3898
3903
  }
3899
- if (!(isValidFilePath(source) || isValidUrl(source))) {
3904
+ if (!(isValidFilePath(sourceContent) || isValidUrl(sourceContent))) {
3900
3905
  throw new ParsingError("Source not valid");
3901
3906
  }
3902
- if (source.startsWith('../') || source.startsWith('/') || /^[A-Z]:[\\/]+/i.test(source)) {
3907
+ if (sourceContent.startsWith('../') || sourceContent.startsWith('/') || /^[A-Z]:[\\/]+/i.test(sourceContent)) {
3903
3908
  throw new ParsingError("Source cannot be outside of the .ptbk.md folder");
3904
3909
  }
3905
3910
  return {
3906
3911
  type: 'KNOWLEDGE',
3907
- source: source,
3912
+ sourceContent: sourceContent,
3908
3913
  };
3909
3914
  },
3910
3915
  /**
3911
3916
  * Note: Prototype of [🍧] (remove this comment after full implementation)
3912
3917
  */
3913
3918
  applyToPipelineJson: function (personaCommand, subjects) {
3914
- var source = personaCommand.source;
3919
+ var sourceContent = personaCommand.sourceContent;
3915
3920
  var pipelineJson = subjects.pipelineJson;
3916
- var name = titleToName(source);
3921
+ var name = 'source-' + sha256__default["default"](hexEncoder__default["default"].parse(JSON.stringify(sourceContent))).toString( /* hex */);
3922
+ // <- TODO: [🥬] Encapsulate sha256 to some private utility function
3923
+ // <- TODO: This should be replaced with a better name later in preparation (done with some propper LLM summarization)
3917
3924
  pipelineJson.knowledgeSources.push({
3918
3925
  name: name,
3919
- source: source,
3926
+ sourceContent: sourceContent,
3920
3927
  });
3921
3928
  },
3922
3929
  };
@@ -4109,7 +4116,7 @@
4109
4116
  'KNOWLEDGE',
4110
4117
  'INSTRUMENT',
4111
4118
  'ACTION',
4112
- // <- [🩻]
4119
+ // <- [🅱]
4113
4120
  ];
4114
4121
 
4115
4122
  /**
@@ -4136,7 +4143,7 @@
4136
4143
  'KNOWLEDGE',
4137
4144
  'INSTRUMENT',
4138
4145
  'ACTION',
4139
- // <- [🩻]
4146
+ // <- [🅱]
4140
4147
  ],
4141
4148
  /**
4142
4149
  * Aliases for the BLOCK command
@@ -5602,7 +5609,7 @@
5602
5609
  if (command.blockType === 'KNOWLEDGE') {
5603
5610
  knowledgeCommandParser.applyToPipelineJson({
5604
5611
  type: 'KNOWLEDGE',
5605
- source: content, // <- TODO: [🐝] !!! Work with KNOWLEDGE which not referring to the source file or website, but its content itself
5612
+ sourceContent: content, // <- TODO: [🐝] !!! Work with KNOWLEDGE which not referring to the source file or website, but its content itself
5606
5613
  }, {
5607
5614
  pipelineJson: pipelineJson,
5608
5615
  templateJson: templateJson,
@@ -6213,7 +6220,7 @@
6213
6220
  }
6214
6221
  else {
6215
6222
  existing = collection.get(pipeline.pipelineUrl);
6216
- throw new ReferenceError(spaceTrim__default["default"]("\n Pipeline with URL \"".concat(pipeline.pipelineUrl, "\" is already in the collection\n\n Conflicting files:\n ").concat(existing.sourceFile || 'Unknown', "\n ").concat(pipeline.sourceFile || 'Unknown', "\n\n Note: Pipelines with the same URL are not allowed\n Only exepction is when the pipelines are identical\n\n ")));
6223
+ throw new ReferenceError(spaceTrim__default["default"]("\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 ")));
6217
6224
  }
6218
6225
  }
6219
6226
  }
@@ -6279,22 +6286,6 @@
6279
6286
  * TODO: [🖇] What about symlinks? Maybe option isSymlinksFollowed
6280
6287
  */
6281
6288
 
6282
- /**
6283
- * This error type indicates that you try to use a feature that is not available in the current environment
6284
- *
6285
- * @public exported from `@promptbook/core`
6286
- */
6287
- var EnvironmentMismatchError = /** @class */ (function (_super) {
6288
- __extends(EnvironmentMismatchError, _super);
6289
- function EnvironmentMismatchError(message) {
6290
- var _this = _super.call(this, message) || this;
6291
- _this.name = 'EnvironmentMismatchError';
6292
- Object.setPrototypeOf(_this, EnvironmentMismatchError.prototype);
6293
- return _this;
6294
- }
6295
- return EnvironmentMismatchError;
6296
- }(Error));
6297
-
6298
6289
  /**
6299
6290
  * Helper of usage compute
6300
6291
  *
@@ -6640,6 +6631,7 @@
6640
6631
  * TODO: Maybe make custom OpenaiError
6641
6632
  * TODO: [🧠][🈁] Maybe use `isDeterministic` from options
6642
6633
  * TODO: [🍜] Auto use anonymous server in browser
6634
+ * TODO: [🧠][🌰] Allow to pass `title` for tracking purposes
6643
6635
  */
6644
6636
 
6645
6637
  /**
@@ -6993,6 +6985,255 @@
6993
6985
  * TODO: [🚸] Not all models are compatible with JSON mode, add this information here and use it
6994
6986
  */
6995
6987
 
6988
+ /**
6989
+ * Execution Tools for calling Azure OpenAI API.
6990
+ *
6991
+ * @public exported from `@promptbook/azure-openai`
6992
+ */
6993
+ var AzureOpenAiExecutionTools = /** @class */ (function () {
6994
+ /**
6995
+ * Creates OpenAI Execution Tools.
6996
+ *
6997
+ * @param options which are relevant are directly passed to the OpenAI client
6998
+ */
6999
+ function AzureOpenAiExecutionTools(options) {
7000
+ this.options = options;
7001
+ this.client = new openai.OpenAIClient("https://".concat(options.resourceName, ".openai.azure.com/"), new openai.AzureKeyCredential(options.apiKey));
7002
+ }
7003
+ Object.defineProperty(AzureOpenAiExecutionTools.prototype, "title", {
7004
+ get: function () {
7005
+ return 'Azure OpenAI';
7006
+ },
7007
+ enumerable: false,
7008
+ configurable: true
7009
+ });
7010
+ Object.defineProperty(AzureOpenAiExecutionTools.prototype, "description", {
7011
+ get: function () {
7012
+ return 'Use all models trained by OpenAI provided by Azure';
7013
+ },
7014
+ enumerable: false,
7015
+ configurable: true
7016
+ });
7017
+ /**
7018
+ * Calls OpenAI API to use a chat model.
7019
+ */
7020
+ AzureOpenAiExecutionTools.prototype.callChatModel = function (prompt) {
7021
+ var _a, _b;
7022
+ return __awaiter(this, void 0, void 0, function () {
7023
+ var content, parameters, modelRequirements, modelName, modelSettings, rawPromptContent, messages, start, complete, rawRequest, rawResponse, resultContent, usage, error_1;
7024
+ var _c;
7025
+ return __generator(this, function (_d) {
7026
+ switch (_d.label) {
7027
+ case 0:
7028
+ if (this.options.isVerbose) {
7029
+ console.info('💬 OpenAI callChatModel call');
7030
+ }
7031
+ content = prompt.content, parameters = prompt.parameters, modelRequirements = prompt.modelRequirements;
7032
+ // TODO: [☂] Use here more modelRequirements
7033
+ if (modelRequirements.modelVariant !== 'CHAT') {
7034
+ throw new PipelineExecutionError('Use callChatModel only for CHAT variant');
7035
+ }
7036
+ _d.label = 1;
7037
+ case 1:
7038
+ _d.trys.push([1, 3, , 4]);
7039
+ modelName = prompt.modelRequirements.modelName || this.options.deploymentName;
7040
+ modelSettings = {
7041
+ maxTokens: modelRequirements.maxTokens,
7042
+ // <- TODO: [🌾] Make some global max cap for maxTokens
7043
+ temperature: modelRequirements.temperature,
7044
+ user: this.options.user,
7045
+ // <- TODO: [🈁] Use `seed` here AND/OR use is `isDeterministic` for entire execution tools
7046
+ // <- Note: [🧆]
7047
+ };
7048
+ rawPromptContent = replaceParameters(content, __assign(__assign({}, parameters), { modelName: modelName }));
7049
+ messages = __spreadArray(__spreadArray([], __read((modelRequirements.systemMessage === undefined
7050
+ ? []
7051
+ : [
7052
+ {
7053
+ role: 'system',
7054
+ content: modelRequirements.systemMessage,
7055
+ },
7056
+ ])), false), [
7057
+ {
7058
+ role: 'user',
7059
+ content: rawPromptContent,
7060
+ },
7061
+ ], false);
7062
+ start = getCurrentIsoDate();
7063
+ complete = void 0;
7064
+ if (this.options.isVerbose) {
7065
+ console.info(colors__default["default"].bgWhite('messages'), JSON.stringify(messages, null, 4));
7066
+ }
7067
+ rawRequest = [modelName, messages, modelSettings];
7068
+ return [4 /*yield*/, (_c = this.client).getChatCompletions.apply(_c, __spreadArray([], __read(rawRequest), false))];
7069
+ case 2:
7070
+ rawResponse = _d.sent();
7071
+ if (this.options.isVerbose) {
7072
+ console.info(colors__default["default"].bgWhite('rawResponse'), JSON.stringify(rawResponse, null, 4));
7073
+ }
7074
+ if (!rawResponse.choices[0]) {
7075
+ throw new PipelineExecutionError('No choises from Azure OpenAI');
7076
+ }
7077
+ if (rawResponse.choices.length > 1) {
7078
+ // TODO: This should be maybe only warning
7079
+ throw new PipelineExecutionError('More than one choise from Azure OpenAI');
7080
+ }
7081
+ if (!rawResponse.choices[0].message || !rawResponse.choices[0].message.content) {
7082
+ throw new PipelineExecutionError('Empty response from Azure OpenAI');
7083
+ }
7084
+ resultContent = rawResponse.choices[0].message.content;
7085
+ // eslint-disable-next-line prefer-const
7086
+ complete = getCurrentIsoDate();
7087
+ usage = {
7088
+ price: uncertainNumber() /* <- TODO: [🐞] Compute usage */,
7089
+ input: __assign({ tokensCount: uncertainNumber((_a = rawResponse.usage) === null || _a === void 0 ? void 0 : _a.promptTokens) }, computeUsageCounts(prompt.content)),
7090
+ output: __assign({ tokensCount: uncertainNumber((_b = rawResponse.usage) === null || _b === void 0 ? void 0 : _b.completionTokens) }, computeUsageCounts(prompt.content)),
7091
+ };
7092
+ return [2 /*return*/, {
7093
+ content: resultContent,
7094
+ modelName: modelName,
7095
+ timing: {
7096
+ start: start,
7097
+ complete: complete,
7098
+ },
7099
+ usage: usage,
7100
+ rawPromptContent: rawPromptContent,
7101
+ rawRequest: rawRequest,
7102
+ rawResponse: rawResponse,
7103
+ // <- [🗯]
7104
+ }];
7105
+ case 3:
7106
+ error_1 = _d.sent();
7107
+ throw this.transformAzureError(error_1);
7108
+ case 4: return [2 /*return*/];
7109
+ }
7110
+ });
7111
+ });
7112
+ };
7113
+ /**
7114
+ * Calls Azure OpenAI API to use a complete model.
7115
+ */
7116
+ AzureOpenAiExecutionTools.prototype.callCompletionModel = function (prompt) {
7117
+ var _a, _b;
7118
+ return __awaiter(this, void 0, void 0, function () {
7119
+ var content, parameters, modelRequirements, modelName, modelSettings, start, complete, rawPromptContent, rawRequest, rawResponse, resultContent, usage, error_2;
7120
+ var _c;
7121
+ return __generator(this, function (_d) {
7122
+ switch (_d.label) {
7123
+ case 0:
7124
+ if (this.options.isVerbose) {
7125
+ console.info('🖋 OpenAI callCompletionModel call');
7126
+ }
7127
+ content = prompt.content, parameters = prompt.parameters, modelRequirements = prompt.modelRequirements;
7128
+ // TODO: [☂] Use here more modelRequirements
7129
+ if (modelRequirements.modelVariant !== 'COMPLETION') {
7130
+ throw new PipelineExecutionError('Use callCompletionModel only for COMPLETION variant');
7131
+ }
7132
+ _d.label = 1;
7133
+ case 1:
7134
+ _d.trys.push([1, 3, , 4]);
7135
+ modelName = prompt.modelRequirements.modelName || this.options.deploymentName;
7136
+ modelSettings = {
7137
+ maxTokens: modelRequirements.maxTokens || 2000,
7138
+ // <- TODO: [🌾] Make some global max cap for maxTokens
7139
+ temperature: modelRequirements.temperature,
7140
+ user: this.options.user,
7141
+ // <- TODO: [🈁] Use `seed` here AND/OR use is `isDeterministic` for entire execution tools
7142
+ // <- Note: [🧆]
7143
+ };
7144
+ start = getCurrentIsoDate();
7145
+ complete = void 0;
7146
+ if (this.options.isVerbose) {
7147
+ console.info(colors__default["default"].bgWhite('content'), JSON.stringify(content, null, 4));
7148
+ console.info(colors__default["default"].bgWhite('parameters'), JSON.stringify(parameters, null, 4));
7149
+ }
7150
+ rawPromptContent = replaceParameters(content, __assign(__assign({}, parameters), { modelName: modelName }));
7151
+ rawRequest = [
7152
+ modelName,
7153
+ [rawPromptContent],
7154
+ modelSettings,
7155
+ ];
7156
+ return [4 /*yield*/, (_c = this.client).getCompletions.apply(_c, __spreadArray([], __read(rawRequest), false))];
7157
+ case 2:
7158
+ rawResponse = _d.sent();
7159
+ if (this.options.isVerbose) {
7160
+ console.info(colors__default["default"].bgWhite('rawResponse'), JSON.stringify(rawResponse, null, 4));
7161
+ }
7162
+ if (!rawResponse.choices[0]) {
7163
+ throw new PipelineExecutionError('No choises from OpenAI');
7164
+ }
7165
+ if (rawResponse.choices.length > 1) {
7166
+ // TODO: This should be maybe only warning
7167
+ throw new PipelineExecutionError('More than one choise from OpenAI');
7168
+ }
7169
+ resultContent = rawResponse.choices[0].text;
7170
+ // eslint-disable-next-line prefer-const
7171
+ complete = getCurrentIsoDate();
7172
+ usage = {
7173
+ price: uncertainNumber() /* <- TODO: [🐞] Compute usage */,
7174
+ input: __assign({ tokensCount: uncertainNumber((_a = rawResponse.usage) === null || _a === void 0 ? void 0 : _a.promptTokens) }, computeUsageCounts(prompt.content)),
7175
+ output: __assign({ tokensCount: uncertainNumber((_b = rawResponse.usage) === null || _b === void 0 ? void 0 : _b.completionTokens) }, computeUsageCounts(prompt.content)),
7176
+ };
7177
+ return [2 /*return*/, {
7178
+ content: resultContent,
7179
+ modelName: modelName,
7180
+ timing: {
7181
+ start: start,
7182
+ complete: complete,
7183
+ },
7184
+ usage: usage,
7185
+ rawPromptContent: rawPromptContent,
7186
+ rawRequest: rawRequest,
7187
+ rawResponse: rawResponse,
7188
+ // <- [🗯]
7189
+ }];
7190
+ case 3:
7191
+ error_2 = _d.sent();
7192
+ throw this.transformAzureError(error_2);
7193
+ case 4: return [2 /*return*/];
7194
+ }
7195
+ });
7196
+ });
7197
+ };
7198
+ // <- Note: [🤖] callXxxModel
7199
+ /**
7200
+ * Changes Azure error (which is not propper Error but object) to propper Error
7201
+ */
7202
+ AzureOpenAiExecutionTools.prototype.transformAzureError = function (azureError) {
7203
+ if (typeof azureError !== 'object' || azureError === null) {
7204
+ return new PipelineExecutionError("Unknown Azure OpenAI error");
7205
+ }
7206
+ var code = azureError.code, message = azureError.message;
7207
+ return new PipelineExecutionError("".concat(code, ": ").concat(message));
7208
+ };
7209
+ /**
7210
+ * List all available Azure OpenAI models that can be used
7211
+ */
7212
+ AzureOpenAiExecutionTools.prototype.listModels = function () {
7213
+ return __awaiter(this, void 0, void 0, function () {
7214
+ return __generator(this, function (_a) {
7215
+ // TODO: !!! Do here some filtering which models are really available as deployment
7216
+ // @see https://management.azure.com/subscriptions/subscriptionId/resourceGroups/resourceGroupName/providers/Microsoft.CognitiveServices/accounts/accountName/deployments?api-version=2023-05-01
7217
+ return [2 /*return*/, OPENAI_MODELS.map(function (_a) {
7218
+ var modelTitle = _a.modelTitle, modelName = _a.modelName, modelVariant = _a.modelVariant;
7219
+ return ({
7220
+ modelTitle: "Azure ".concat(modelTitle),
7221
+ modelName: modelName,
7222
+ modelVariant: modelVariant,
7223
+ });
7224
+ })];
7225
+ });
7226
+ });
7227
+ };
7228
+ return AzureOpenAiExecutionTools;
7229
+ }());
7230
+ /**
7231
+ * TODO: Maybe Create some common util for callChatModel and callCompletionModel
7232
+ * TODO: Maybe make custom AzureOpenaiError
7233
+ * TODO: [🧠][🈁] Maybe use `isDeterministic` from options
7234
+ * TODO: [🧠][🌰] Allow to pass `title` for tracking purposes
7235
+ */
7236
+
6996
7237
  /**
6997
7238
  * Computes the usage of the OpenAI API based on the response from OpenAI
6998
7239
  *
@@ -7329,12 +7570,104 @@
7329
7570
  * TODO: Maybe Create some common util for callChatModel and callCompletionModel
7330
7571
  * TODO: Maybe make custom OpenaiError
7331
7572
  * TODO: [🧠][🈁] Maybe use `isDeterministic` from options
7573
+ * TODO: [🧠][🌰] Allow to pass `title` for tracking purposes
7574
+ */
7575
+
7576
+ /**
7577
+ * @public exported from `@promptbook/node`
7578
+ */
7579
+ var LLM_CONFIGURATION_BOILERPLATES = [
7580
+ {
7581
+ title: 'Open AI',
7582
+ packageName: '@promptbook/openai',
7583
+ className: 'OpenAiExecutionTools',
7584
+ options: {
7585
+ apiKey: 'sk-',
7586
+ },
7587
+ },
7588
+ {
7589
+ title: 'Anthropic Claude',
7590
+ packageName: '@promptbook/anthropic-claude',
7591
+ className: 'AnthropicClaudeExecutionTools',
7592
+ options: {
7593
+ apiKey: 'sk-ant-api03-',
7594
+ },
7595
+ },
7596
+ {
7597
+ title: 'Azure Open AI',
7598
+ packageName: '@promptbook/azure-openai',
7599
+ className: 'AzureOpenAiExecutionTools',
7600
+ options: {
7601
+ // TODO: !!!> resourceName
7602
+ // TODO: !!!> deploymentName
7603
+ apiKey: 'sk-',
7604
+ },
7605
+ },
7606
+ // <- Note: [🦑] Add here new LLM provider
7607
+ ];
7608
+ /**
7609
+ * @private internal type for `createLlmToolsFromConfiguration`
7332
7610
  */
7611
+ var EXECUTION_TOOLS_CLASSES = {
7612
+ getOpenAiExecutionTools: function (options) {
7613
+ return new OpenAiExecutionTools(__assign(__assign({}, options), { dangerouslyAllowBrowser: true /* <- TODO: [🧠] !!! Some mechanism for auto-detection of browser, maybe hide in `OpenAiExecutionTools` */ }));
7614
+ },
7615
+ getAnthropicClaudeExecutionTools: function (options) { return new AnthropicClaudeExecutionTools(options); },
7616
+ getAzureOpenAiExecutionTools: function (options) { return new AzureOpenAiExecutionTools(options); },
7617
+ // <- Note: [🦑] Add here new LLM provider
7618
+ };
7619
+ /**
7620
+ * TODO: [🧠] Better file name than `config.ts` + maybe move to two separate files
7621
+ * TODO: [🧠][🎌] Adding this should be responsibility of each provider package NOT this one central place
7622
+ */
7623
+
7624
+ /**
7625
+ * This error type indicates that you try to use a feature that is not available in the current environment
7626
+ *
7627
+ * @public exported from `@promptbook/core`
7628
+ */
7629
+ var EnvironmentMismatchError = /** @class */ (function (_super) {
7630
+ __extends(EnvironmentMismatchError, _super);
7631
+ function EnvironmentMismatchError(message) {
7632
+ var _this = _super.call(this, message) || this;
7633
+ _this.name = 'EnvironmentMismatchError';
7634
+ Object.setPrototypeOf(_this, EnvironmentMismatchError.prototype);
7635
+ return _this;
7636
+ }
7637
+ return EnvironmentMismatchError;
7638
+ }(Error));
7333
7639
 
7334
7640
  /**
7335
7641
  * @@@
7336
7642
  *
7337
- * Note: This function is not cached, every call creates new instance of `LlmExecutionTools`
7643
+ * Note: This function is not cached, every call creates new instance of `MultipleLlmExecutionTools`
7644
+ *
7645
+ * @returns @@@
7646
+ * @public exported from `@promptbook/node`
7647
+ */
7648
+ function createLlmToolsFromConfiguration(configuration, options) {
7649
+ if (options === void 0) { options = {}; }
7650
+ if (!isRunningInNode()) {
7651
+ throw new EnvironmentMismatchError('Function `createLlmToolsFromEnv` works only in Node.js environment');
7652
+ }
7653
+ var _a = options.isVerbose, isVerbose = _a === void 0 ? false : _a;
7654
+ dotenv__namespace.config();
7655
+ var llmTools = configuration.map(function (llmConfiguration) {
7656
+ return EXECUTION_TOOLS_CLASSES["get".concat(llmConfiguration.className)](__assign({ isVerbose: isVerbose }, llmConfiguration.options));
7657
+ });
7658
+ return joinLlmExecutionTools.apply(void 0, __spreadArray([], __read(llmTools), false));
7659
+ }
7660
+ /**
7661
+ * TODO: [🧠][🎌] Dynamically install required providers
7662
+ * TODO: @@@ write discussion about this - wizzard
7663
+ * TODO: [🧠][🍛] Which name is better `createLlmToolsFromConfig` or `createLlmToolsFromConfiguration`?
7664
+ * TODO: [🧠] Is there some meaningfull way how to test this util
7665
+ * Note: [🟢] This code should never be published outside of `@promptbook/node` and `@promptbook/cli` and `@promptbook/cli`
7666
+ * TODO: This should be maybe not under `_common` but under `utils`
7667
+ */
7668
+
7669
+ /**
7670
+ * @@@
7338
7671
  *
7339
7672
  * @@@ .env
7340
7673
  *
@@ -7345,46 +7678,77 @@
7345
7678
  * @returns @@@
7346
7679
  * @public exported from `@promptbook/node`
7347
7680
  */
7348
- function createLlmToolsFromEnv(options) {
7349
- if (options === void 0) { options = {}; }
7681
+ function createLlmToolsFromConfigurationFromEnv() {
7350
7682
  if (!isRunningInNode()) {
7351
7683
  throw new EnvironmentMismatchError('Function `createLlmToolsFromEnv` works only in Node.js environment');
7352
7684
  }
7353
- var _a = options.isVerbose, isVerbose = _a === void 0 ? false : _a;
7354
- dotenv__namespace.config();
7355
- var llmTools = [];
7685
+ var llmToolsConfiguration = [];
7356
7686
  if (typeof process.env.OPENAI_API_KEY === 'string') {
7357
- llmTools.push(new OpenAiExecutionTools({
7358
- isVerbose: isVerbose,
7359
- apiKey: process.env.OPENAI_API_KEY,
7360
- }));
7687
+ llmToolsConfiguration.push({
7688
+ title: 'OpenAI (from env)',
7689
+ packageName: '@promptbook/openai',
7690
+ className: 'OpenAiExecutionTools',
7691
+ options: {
7692
+ apiKey: process.env.OPENAI_API_KEY,
7693
+ },
7694
+ });
7361
7695
  }
7362
7696
  if (typeof process.env.ANTHROPIC_CLAUDE_API_KEY === 'string') {
7363
- llmTools.push(new AnthropicClaudeExecutionTools({
7364
- isVerbose: isVerbose,
7365
- apiKey: process.env.ANTHROPIC_CLAUDE_API_KEY,
7366
- }));
7367
- }
7368
- if (llmTools.length === 0) {
7369
- throw new Error(spaceTrim__default["default"]("\n No LLM tools found in the environment\n\n Please set one of environment variables:\n - OPENAI_API_KEY\n - ANTHROPIC_CLAUDE_API_KEY\n "));
7697
+ llmToolsConfiguration.push({
7698
+ title: 'Claude (from env)',
7699
+ packageName: '@promptbook/antrhopic-claude',
7700
+ className: 'AnthropicClaudeExecutionTools',
7701
+ options: {
7702
+ apiKey: process.env.ANTHROPIC_CLAUDE_API_KEY,
7703
+ },
7704
+ });
7370
7705
  }
7371
- else if (llmTools.length === 1) {
7372
- return llmTools[0];
7706
+ // <- Note: [🦑] Add here new LLM provider
7707
+ return llmToolsConfiguration;
7708
+ }
7709
+ /**
7710
+ * TODO: Add Azure OpenAI
7711
+ * TODO: [🧠][🍛]
7712
+ * TODO: [🧠] Is there some meaningfull way how to test this util
7713
+ * Note: [🟢] This code should never be published outside of `@promptbook/node` and `@promptbook/cli` and `@promptbook/cli`
7714
+ * TODO: [👷‍♂️] @@@ Manual about construction of llmTools
7715
+ * TODO: This should be maybe not under `_common` but under `utils`
7716
+ * TODO: [🧠] Maybe pass env as argument
7717
+ */
7718
+
7719
+ /**
7720
+ * @@@
7721
+ *
7722
+ * Note: This function is not cached, every call creates new instance of `MultipleLlmExecutionTools`
7723
+ *
7724
+ * @@@ .env
7725
+ *
7726
+ * It looks for environment variables:
7727
+ * - `process.env.OPENAI_API_KEY`
7728
+ * - `process.env.ANTHROPIC_CLAUDE_API_KEY`
7729
+ *
7730
+ * @returns @@@
7731
+ * @public exported from `@promptbook/node`
7732
+ */
7733
+ function createLlmToolsFromEnv(options) {
7734
+ if (options === void 0) { options = {}; }
7735
+ if (!isRunningInNode()) {
7736
+ throw new EnvironmentMismatchError('Function `createLlmToolsFromEnv` works only in Node.js environment');
7373
7737
  }
7374
- else {
7375
- return joinLlmExecutionTools.apply(void 0, __spreadArray([], __read(llmTools), false));
7738
+ var configuration = createLlmToolsFromConfigurationFromEnv();
7739
+ if (configuration.length === 0) {
7740
+ // TODO: [🥃]
7741
+ throw new Error(spaceTrim__default["default"]("\n No LLM tools found in the environment\n\n Please set one of environment variables:\n - OPENAI_API_KEY\n - ANTHROPIC_CLAUDE_API_KEY\n "));
7376
7742
  }
7743
+ return createLlmToolsFromConfiguration(configuration, options);
7377
7744
  }
7378
7745
  /**
7379
- * TODO: [🍜] Use `createLlmToolsFromConfiguration`
7380
- * TODO: @@@ write discussion about this - wizzard
7381
- * TODO: Add Azure
7382
- * TODO: [🧠] Which name is better `createLlmToolsFromEnv` or `createLlmToolsFromEnvironment`?
7746
+ * TODO: @@@ write `createLlmToolsFromEnv` vs `createLlmToolsFromConfigurationFromEnv` vs `createLlmToolsFromConfiguration`
7747
+ * TODO: [🧠][🍛] Which name is better `createLlmToolsFromEnv` or `createLlmToolsFromEnvironment`?
7383
7748
  * TODO: [🧠] Is there some meaningfull way how to test this util
7384
- * TODO: [🧠] Maybe pass env as argument
7385
7749
  * Note: [🟢] This code should never be published outside of `@promptbook/node` and `@promptbook/cli` and `@promptbook/cli`
7386
- * TODO: [👷‍♂️] @@@ Manual about construction of llmTools
7387
7750
  * TODO: [🥃] Allow `ptbk make` without llm tools
7751
+ * TODO: This should be maybe not under `_common` but under `utils`
7388
7752
  */
7389
7753
 
7390
7754
  /**
@@ -7438,6 +7802,7 @@
7438
7802
  FilesStorage.prototype.getFilenameForKey = function (key) {
7439
7803
  var name = titleToName(key);
7440
7804
  var hash = sha256__default["default"](hexEncoder__default["default"].parse(name)).toString( /* hex */);
7805
+ // <- TODO: [🥬] Encapsulate sha256 to some private utility function
7441
7806
  return path.join.apply(void 0, __spreadArray(__spreadArray([this.options.cacheFolderPath], __read(nameToSubfolderPath(hash /* <- TODO: [🎎] Maybe add some SHA256 prefix */)), false), ["".concat(name.substring(0, MAX_FILENAME_LENGTH), ".json")], false));
7442
7807
  };
7443
7808
  /**
@@ -7515,8 +7880,11 @@
7515
7880
  */
7516
7881
 
7517
7882
  exports.FilesStorage = FilesStorage;
7883
+ exports.LLM_CONFIGURATION_BOILERPLATES = LLM_CONFIGURATION_BOILERPLATES;
7518
7884
  exports.PROMPTBOOK_VERSION = PROMPTBOOK_VERSION;
7519
7885
  exports.createCollectionFromDirectory = createCollectionFromDirectory;
7886
+ exports.createLlmToolsFromConfiguration = createLlmToolsFromConfiguration;
7887
+ exports.createLlmToolsFromConfigurationFromEnv = createLlmToolsFromConfigurationFromEnv;
7520
7888
  exports.createLlmToolsFromEnv = createLlmToolsFromEnv;
7521
7889
 
7522
7890
  Object.defineProperty(exports, '__esModule', { value: true });