@promptbook/cli 0.74.0-6 → 0.74.0-8

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.
@@ -1,4 +1,6 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env node --no-warnings
2
+
3
+ // <- TODO: !!!!!! Is this try to get rid of deprecation warnings in node v23.2.0 working?
2
4
 
3
5
  const { _CLI /* <- Note: [🥠] */ } = require('../umd/index.umd.js');
4
6
 
package/esm/index.es.js CHANGED
@@ -1,6 +1,6 @@
1
+ import colors from 'colors';
1
2
  import commander from 'commander';
2
3
  import spaceTrim$1, { spaceTrim } from 'spacetrim';
3
- import colors from 'colors';
4
4
  import { forTime } from 'waitasecond';
5
5
  import { stat, access, constants, readFile, writeFile, readdir, mkdir, unlink, rm, rmdir, rename } from 'fs/promises';
6
6
  import { join, basename, dirname } from 'path';
@@ -37,7 +37,7 @@ var BOOK_LANGUAGE_VERSION = '1.0.0';
37
37
  *
38
38
  * @see https://github.com/webgptorg/promptbook
39
39
  */
40
- var PROMPTBOOK_ENGINE_VERSION = '0.74.0-5';
40
+ var PROMPTBOOK_ENGINE_VERSION = '0.74.0-7';
41
41
  /**
42
42
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
43
43
  */
@@ -3199,10 +3199,12 @@ function countLines(text) {
3199
3199
  * @public exported from `@promptbook/utils`
3200
3200
  */
3201
3201
  function countPages(text) {
3202
- var sentencesPerPage = 5; // Assuming each page has 5 sentences
3203
- var sentences = text.split(/[.!?]+/).filter(function (sentence) { return sentence.trim() !== ''; });
3204
- var pageCount = Math.ceil(sentences.length / sentencesPerPage);
3205
- return pageCount;
3202
+ if (text === '') {
3203
+ return 0;
3204
+ }
3205
+ var pagesByLinesCount = Math.ceil(countLines(text) / 44);
3206
+ var pagesByCharactersCount = Math.ceil(countCharacters(text) / 2772);
3207
+ return Math.max(pagesByLinesCount, pagesByCharactersCount);
3206
3208
  }
3207
3209
 
3208
3210
  /**
@@ -7926,7 +7928,7 @@ function titleToName(value) {
7926
7928
  * @public exported from `@promptbook/core`
7927
7929
  */
7928
7930
  function pipelineStringToJsonSync(pipelineString) {
7929
- var e_1, _a, e_2, _b;
7931
+ var e_1, _a, e_2, _b, e_3, _c, e_4, _d;
7930
7932
  var $pipelineJson = {
7931
7933
  title: undefined /* <- Note: [🍙] Putting here placeholder to keep `title` on top at final JSON */,
7932
7934
  pipelineUrl: undefined /* <- Note: Putting here placeholder to keep `pipelineUrl` on top at final JSON */,
@@ -7953,11 +7955,18 @@ function pipelineStringToJsonSync(pipelineString) {
7953
7955
  }
7954
7956
  // =============================================================
7955
7957
  // Note: 1️⃣ Parsing of the markdown into object
7958
+ if (pipelineString.startsWith('#!')) {
7959
+ var _e = __read(pipelineString.split('\n')), shebangLine_1 = _e[0], restLines = _e.slice(1);
7960
+ if (!(shebangLine_1 || '').includes('ptbk')) {
7961
+ throw new ParseError(spaceTrim(function (block) { return "\n It seems that you try to parse a book file which has non-standard shebang line for book files:\n Shebang line must contain 'ptbk'\n\n You have:\n ".concat(block(shebangLine_1 || '(empty line)'), "\n\n It should look like this:\n #!/usr/bin/env ptbk\n\n ").concat(block(getPipelineIdentification()), "\n "); }));
7962
+ }
7963
+ pipelineString = restLines.join('\n');
7964
+ }
7956
7965
  pipelineString = removeContentComments(pipelineString);
7957
7966
  pipelineString = flattenMarkdown(pipelineString) /* <- Note: [🥞] */;
7958
7967
  pipelineString = pipelineString.replaceAll(/`\{(?<parameterName>[a-z0-9_]+)\}`/gi, '{$<parameterName>}');
7959
7968
  pipelineString = pipelineString.replaceAll(/`->\s+\{(?<parameterName>[a-z0-9_]+)\}`/gi, '-> {$<parameterName>}');
7960
- var _c = __read(splitMarkdownIntoSections(pipelineString).map(parseMarkdownSection)), pipelineHead = _c[0], pipelineSections = _c.slice(1); /* <- Note: [🥞] */
7969
+ var _f = __read(splitMarkdownIntoSections(pipelineString).map(parseMarkdownSection)), pipelineHead = _f[0], pipelineSections = _f.slice(1); /* <- Note: [🥞] */
7961
7970
  if (pipelineHead === undefined) {
7962
7971
  throw new UnexpectedError(spaceTrim(function (block) { return "\n Pipeline head is not defined\n\n ".concat(block(getPipelineIdentification()), "\n\n This should never happen, because the pipeline already flattened\n "); }));
7963
7972
  }
@@ -7985,6 +7994,8 @@ function pipelineStringToJsonSync(pipelineString) {
7985
7994
  if (parameterDescription) {
7986
7995
  existingParameter.description = parameterDescription;
7987
7996
  }
7997
+ existingParameter.isInput = existingParameter.isInput || isInput;
7998
+ existingParameter.isOutput = existingParameter.isOutput || isOutput;
7988
7999
  }
7989
8000
  else {
7990
8001
  $pipelineJson.parameters.push({
@@ -8047,10 +8058,10 @@ function pipelineStringToJsonSync(pipelineString) {
8047
8058
  finally { if (e_1) throw e_1.error; }
8048
8059
  }
8049
8060
  var _loop_2 = function (section) {
8050
- var e_3, _d;
8061
+ var e_5, _l, e_6, _m;
8051
8062
  // TODO: Parse template description (the content out of the codeblock and lists)
8052
8063
  var listItems_2 = extractAllListItemsFromMarkdown(section.content);
8053
- var _e = extractOneBlockFromMarkdown(section.content), language = _e.language, content = _e.content;
8064
+ var _o = extractOneBlockFromMarkdown(section.content), language = _o.language, content = _o.content;
8054
8065
  // TODO: [🎾][1] DRY description
8055
8066
  var description_1 = section.content;
8056
8067
  // Note: Remove codeblocks - TODO: [🎾]
@@ -8091,7 +8102,7 @@ function pipelineStringToJsonSync(pipelineString) {
8091
8102
  }) === false) {
8092
8103
  templateCommandParser.$applyToTemplateJson({ type: 'TEMPLATE', templateType: 'PROMPT_TEMPLATE' }, $templateJson, $pipelineJson);
8093
8104
  }
8094
- var _loop_3 = function (listItem, command) {
8105
+ var _loop_4 = function (listItem, command) {
8095
8106
  var commandParser = getParserForCommand(command);
8096
8107
  if (commandParser.isUsedInPipelineTemplate !== true /* <- Note: [🦦][4] */) {
8097
8108
  throw new ParseError(spaceTrim(function (block) { return "\n Command ".concat(command.type, " is not allowed in the template of the promptbook ONLY at the pipeline head\n\n ").concat(block(getPipelineIdentification()), "\n "); })); // <- TODO: [🚞]
@@ -8114,17 +8125,17 @@ function pipelineStringToJsonSync(pipelineString) {
8114
8125
  };
8115
8126
  try {
8116
8127
  // TODO [♓️] List commands and before apply order them to achieve order-agnostic commands
8117
- for (var commands_1 = (e_3 = void 0, __values(commands)), commands_1_1 = commands_1.next(); !commands_1_1.done; commands_1_1 = commands_1.next()) {
8118
- var _f = commands_1_1.value, listItem = _f.listItem, command = _f.command;
8119
- _loop_3(listItem, command);
8128
+ for (var commands_1 = (e_5 = void 0, __values(commands)), commands_1_1 = commands_1.next(); !commands_1_1.done; commands_1_1 = commands_1.next()) {
8129
+ var _p = commands_1_1.value, listItem = _p.listItem, command = _p.command;
8130
+ _loop_4(listItem, command);
8120
8131
  }
8121
8132
  }
8122
- catch (e_3_1) { e_3 = { error: e_3_1 }; }
8133
+ catch (e_5_1) { e_5 = { error: e_5_1 }; }
8123
8134
  finally {
8124
8135
  try {
8125
- if (commands_1_1 && !commands_1_1.done && (_d = commands_1.return)) _d.call(commands_1);
8136
+ if (commands_1_1 && !commands_1_1.done && (_l = commands_1.return)) _l.call(commands_1);
8126
8137
  }
8127
- finally { if (e_3) throw e_3.error; }
8138
+ finally { if (e_5) throw e_5.error; }
8128
8139
  }
8129
8140
  // TODO: [🍧] Should be done in TEMPLATE command
8130
8141
  if ($templateJson.templateType === 'SCRIPT_TEMPLATE') {
@@ -8138,6 +8149,26 @@ function pipelineStringToJsonSync(pipelineString) {
8138
8149
  language;
8139
8150
  }
8140
8151
  $templateJson.dependentParameterNames = Array.from(extractParameterNamesFromTemplate($templateJson));
8152
+ try {
8153
+ for (var _q = (e_6 = void 0, __values($templateJson.dependentParameterNames)), _r = _q.next(); !_r.done; _r = _q.next()) {
8154
+ var parameterName = _r.value;
8155
+ // TODO: [🧠] This definition should be made first in the template
8156
+ defineParam({
8157
+ parameterName: parameterName,
8158
+ parameterDescription: null,
8159
+ isInput: false,
8160
+ isOutput: false,
8161
+ // <- Note: In this case null+false+false means that we do not know yet if it is input or output and we will set it later
8162
+ });
8163
+ }
8164
+ }
8165
+ catch (e_6_1) { e_6 = { error: e_6_1 }; }
8166
+ finally {
8167
+ try {
8168
+ if (_r && !_r.done && (_m = _q.return)) _m.call(_q);
8169
+ }
8170
+ finally { if (e_6) throw e_6.error; }
8171
+ }
8141
8172
  /*
8142
8173
  // TODO: [🍧] This should be checked in `MODEL` command + better error message
8143
8174
  if ($templateJson.templateType !== 'PROMPT_TEMPLATE' && $templateJson.modelRequirements !== undefined) {
@@ -8179,9 +8210,51 @@ function pipelineStringToJsonSync(pipelineString) {
8179
8210
  finally { if (e_2) throw e_2.error; }
8180
8211
  }
8181
8212
  // =============================================================
8182
- // Note: 5️⃣ Cleanup of undefined values
8213
+ // Note: 5️⃣ Mark parameters as INPUT if not explicitly set
8214
+ if ($pipelineJson.parameters.every(function (parameter) { return !parameter.isInput; })) {
8215
+ var _loop_3 = function (parameter) {
8216
+ var isThisParameterResulting = $pipelineJson.templates.some(function (template) { return template.resultingParameterName === parameter.name; });
8217
+ if (!isThisParameterResulting) {
8218
+ parameter.isInput = true;
8219
+ }
8220
+ };
8221
+ try {
8222
+ for (var _g = __values($pipelineJson.parameters), _h = _g.next(); !_h.done; _h = _g.next()) {
8223
+ var parameter = _h.value;
8224
+ _loop_3(parameter);
8225
+ }
8226
+ }
8227
+ catch (e_3_1) { e_3 = { error: e_3_1 }; }
8228
+ finally {
8229
+ try {
8230
+ if (_h && !_h.done && (_c = _g.return)) _c.call(_g);
8231
+ }
8232
+ finally { if (e_3) throw e_3.error; }
8233
+ }
8234
+ }
8235
+ // =============================================================
8236
+ // Note: 6️⃣ Mark all non-INPUT parameters as OUTPUT if any OUTPUT is not set
8237
+ if ($pipelineJson.parameters.every(function (parameter) { return !parameter.isOutput; })) {
8238
+ try {
8239
+ for (var _j = __values($pipelineJson.parameters), _k = _j.next(); !_k.done; _k = _j.next()) {
8240
+ var parameter = _k.value;
8241
+ if (!parameter.isInput) {
8242
+ parameter.isOutput = true;
8243
+ }
8244
+ }
8245
+ }
8246
+ catch (e_4_1) { e_4 = { error: e_4_1 }; }
8247
+ finally {
8248
+ try {
8249
+ if (_k && !_k.done && (_d = _j.return)) _d.call(_j);
8250
+ }
8251
+ finally { if (e_4) throw e_4.error; }
8252
+ }
8253
+ }
8254
+ // =============================================================
8255
+ // Note: 7️⃣ Cleanup of undefined values
8183
8256
  $pipelineJson.templates.forEach(function (templates) {
8184
- var e_4, _a;
8257
+ var e_7, _a;
8185
8258
  try {
8186
8259
  for (var _b = __values(Object.entries(templates)), _c = _b.next(); !_c.done; _c = _b.next()) {
8187
8260
  var _d = __read(_c.value, 2), key = _d[0], value = _d[1];
@@ -8190,16 +8263,16 @@ function pipelineStringToJsonSync(pipelineString) {
8190
8263
  }
8191
8264
  }
8192
8265
  }
8193
- catch (e_4_1) { e_4 = { error: e_4_1 }; }
8266
+ catch (e_7_1) { e_7 = { error: e_7_1 }; }
8194
8267
  finally {
8195
8268
  try {
8196
8269
  if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
8197
8270
  }
8198
- finally { if (e_4) throw e_4.error; }
8271
+ finally { if (e_7) throw e_7.error; }
8199
8272
  }
8200
8273
  });
8201
8274
  $pipelineJson.parameters.forEach(function (parameter) {
8202
- var e_5, _a;
8275
+ var e_8, _a;
8203
8276
  try {
8204
8277
  for (var _b = __values(Object.entries(parameter)), _c = _b.next(); !_c.done; _c = _b.next()) {
8205
8278
  var _d = __read(_c.value, 2), key = _d[0], value = _d[1];
@@ -8208,12 +8281,12 @@ function pipelineStringToJsonSync(pipelineString) {
8208
8281
  }
8209
8282
  }
8210
8283
  }
8211
- catch (e_5_1) { e_5 = { error: e_5_1 }; }
8284
+ catch (e_8_1) { e_8 = { error: e_8_1 }; }
8212
8285
  finally {
8213
8286
  try {
8214
8287
  if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
8215
8288
  }
8216
- finally { if (e_5) throw e_5.error; }
8289
+ finally { if (e_8) throw e_8.error; }
8217
8290
  }
8218
8291
  });
8219
8292
  // =============================================================
@@ -10974,10 +11047,10 @@ function initializeRunCommand(program) {
10974
11047
  runCommand.option('-v, --verbose', "Is output verbose", false);
10975
11048
  runCommand.option('--no-interactive', "Input is not interactive", false);
10976
11049
  runCommand.option('-s, --save-report <path>', "Save report to file");
10977
- // TODO: !!!!!! Interactive mode
11050
+ // TODO: !!!!!! Implement non-interactive mode - allow to pass input parameters as JSON
10978
11051
  // TODO: !!!!!! JSON output
10979
11052
  runCommand.action(function (filePathRaw, options) { return __awaiter(_this, void 0, void 0, function () {
10980
- var isCacheReloaded, isVerbose, saveReport, prepareAndScrapeOptions, fs, filePath, filePathCandidates, filePathCandidates_1, filePathCandidates_1_1, filePathCandidate, e_1_1, llm, executables, tools, pipelineString, pipeline, pipelineExecutor, questions, response, inputParameters, result, isSuccessful, errors, warnings, outputParameters, executionReport, executionReportString, _a, _b, error, _c, _d, warning, _e, _f, key, value, separator;
11053
+ var isCacheReloaded, isVerbose, saveReport, prepareAndScrapeOptions, fs, filePath, filePathCandidates, filePathCandidates_1, filePathCandidates_1_1, filePathCandidate, e_1_1, llm, executables, tools, pipelineString, pipeline, error_1, pipelineExecutor, questions, response, inputParameters, result, isSuccessful, errors, warnings, outputParameters, executionReport, executionReportString, _a, _b, error, _c, _d, warning, _e, _f, key, value, separator;
10981
11054
  var e_1, _g, _h, e_2, _j, e_3, _k, e_4, _l;
10982
11055
  return __generator(this, function (_m) {
10983
11056
  switch (_m.label) {
@@ -11076,12 +11149,25 @@ function initializeRunCommand(program) {
11076
11149
  if (isVerbose) {
11077
11150
  console.info(colors.gray('--- Preparing pipeline ---'));
11078
11151
  }
11079
- return [4 /*yield*/, pipelineStringToJson(pipelineString, tools)];
11152
+ _m.label = 12;
11080
11153
  case 12:
11154
+ _m.trys.push([12, 14, , 15]);
11155
+ return [4 /*yield*/, pipelineStringToJson(pipelineString, tools)];
11156
+ case 13:
11081
11157
  pipeline = _m.sent();
11158
+ return [3 /*break*/, 15];
11159
+ case 14:
11160
+ error_1 = _m.sent();
11161
+ if (!(error_1 instanceof ParseError)) {
11162
+ throw error_1;
11163
+ }
11164
+ console.error(colors.red(spaceTrim$1(function (block) { return "\n ".concat(block(error_1.message), "\n\n in ").concat(filePath, "\n "); })));
11165
+ return [2 /*return*/, process.exit(1)];
11166
+ case 15:
11082
11167
  if (isVerbose) {
11083
11168
  console.info(colors.gray('--- Validating pipeline ---'));
11084
11169
  }
11170
+ // TODO: !!!!!! Same try-catch for LogicError
11085
11171
  validatePipeline(pipeline);
11086
11172
  if (isVerbose) {
11087
11173
  console.info(colors.gray('--- Creating executor ---'));
@@ -11103,16 +11189,26 @@ function initializeRunCommand(program) {
11103
11189
  return isInput;
11104
11190
  })
11105
11191
  .map(function (_a) {
11106
- var name = _a.name;
11107
- return ({
11192
+ var name = _a.name, exampleValues = _a.exampleValues;
11193
+ var message = name;
11194
+ var initial = '';
11195
+ if (exampleValues && exampleValues.length > 0) {
11196
+ var exampleValuesFiltered = exampleValues.filter(function (exampleValue) { return countLines(exampleValue) <= 1 && countCharacters(exampleValue) <= 30; });
11197
+ if (exampleValuesFiltered.length !== 0) {
11198
+ message += " (e.g. ".concat(exampleValuesFiltered.join(', '), ")");
11199
+ }
11200
+ initial = exampleValues[0] || '';
11201
+ }
11202
+ return {
11108
11203
  type: 'text',
11109
11204
  name: name,
11110
- message: name,
11205
+ message: message,
11206
+ initial: initial,
11111
11207
  // TODO: Maybe use> validate: value => value < 18 ? `Forbidden` : true
11112
- });
11208
+ };
11113
11209
  });
11114
11210
  return [4 /*yield*/, prompts(questions)];
11115
- case 13:
11211
+ case 16:
11116
11212
  response = _m.sent();
11117
11213
  inputParameters = response;
11118
11214
  if (isVerbose) {
@@ -11124,26 +11220,26 @@ function initializeRunCommand(program) {
11124
11220
  console.info(taskProgress);
11125
11221
  }
11126
11222
  })];
11127
- case 14:
11223
+ case 17:
11128
11224
  result = _m.sent();
11129
11225
  isSuccessful = result.isSuccessful, errors = result.errors, warnings = result.warnings, outputParameters = result.outputParameters, executionReport = result.executionReport;
11130
11226
  if (isVerbose) {
11131
11227
  console.info(colors.gray('--- Detailed Result ---'));
11132
11228
  console.info({ isSuccessful: isSuccessful, errors: errors, warnings: warnings, outputParameters: outputParameters, executionReport: executionReport });
11133
11229
  }
11134
- if (!(saveReport && saveReport.endsWith('.json'))) return [3 /*break*/, 16];
11230
+ if (!(saveReport && saveReport.endsWith('.json'))) return [3 /*break*/, 19];
11135
11231
  return [4 /*yield*/, writeFile(saveReport, JSON.stringify(executionReport, null, 4) + '\n', 'utf-8')];
11136
- case 15:
11232
+ case 18:
11137
11233
  _m.sent();
11138
- return [3 /*break*/, 18];
11139
- case 16:
11140
- if (!(saveReport && saveReport.endsWith('.md'))) return [3 /*break*/, 18];
11234
+ return [3 /*break*/, 21];
11235
+ case 19:
11236
+ if (!(saveReport && saveReport.endsWith('.md'))) return [3 /*break*/, 21];
11141
11237
  executionReportString = executionReportJsonToString(executionReport);
11142
11238
  return [4 /*yield*/, writeFile(saveReport, executionReportString, 'utf-8')];
11143
- case 17:
11239
+ case 20:
11144
11240
  _m.sent();
11145
- _m.label = 18;
11146
- case 18:
11241
+ _m.label = 21;
11242
+ case 21:
11147
11243
  if (saveReport && isVerbose) {
11148
11244
  console.info(colors.green("Report saved to ".concat(saveReport)));
11149
11245
  }
@@ -11337,11 +11433,16 @@ function initializeTestCommand(program) {
11337
11433
  */
11338
11434
  function promptbookCli() {
11339
11435
  return __awaiter(this, void 0, void 0, function () {
11340
- var program;
11436
+ var isVerbose, program;
11341
11437
  return __generator(this, function (_a) {
11342
11438
  if (!$isRunningInNode()) {
11343
11439
  throw new EnvironmentMismatchError(spaceTrim("\n Function promptbookCli is initiator of CLI script and should be run in Node.js environment.\n\n - In browser use function exported from `@promptbook/utils` or `@promptbook/core` directly, for example `prettifyPipelineString`.\n\n "));
11344
11440
  }
11441
+ isVerbose = process.argv.some(function (arg) { return arg === '--verbose' || arg === '-v'; });
11442
+ // <- TODO: Can be this be done with commander before the commander commands are initialized?
11443
+ if (isVerbose) {
11444
+ console.info(colors.gray("Promptbook CLI version ".concat(PROMPTBOOK_ENGINE_VERSION, " in ").concat(__filename.split('\\').join('/'))));
11445
+ }
11345
11446
  program = new commander.Command();
11346
11447
  program.name('promptbook');
11347
11448
  program.alias('ptbk');
@@ -13675,12 +13776,9 @@ function $execCommandNormalizeOptions(options) {
13675
13776
  })
13676
13777
  .filter(function (arg) { return arg !== ''; });
13677
13778
  if (_.length > 1) {
13678
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
13679
13779
  _a = __read(_), command = _a[0], args = _a.slice(1);
13680
13780
  }
13681
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
13682
13781
  if (options.args) {
13683
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
13684
13782
  args = __spreadArray(__spreadArray([], __read(args), false), __read(options.args), false);
13685
13783
  }
13686
13784
  var humanReadableCommand = !['npx', 'npm'].includes(command) ? command : args[0];