@promptbook/cli 0.88.0 → 0.89.0-2

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 (30) hide show
  1. package/README.md +4 -0
  2. package/esm/index.es.js +207 -102
  3. package/esm/index.es.js.map +1 -1
  4. package/esm/typings/src/_packages/core.index.d.ts +6 -2
  5. package/esm/typings/src/_packages/types.index.d.ts +16 -4
  6. package/esm/typings/src/cli/cli-commands/login.d.ts +15 -0
  7. package/esm/typings/src/execution/PipelineExecutorResult.d.ts +2 -2
  8. package/esm/typings/src/execution/PromptResult.d.ts +2 -2
  9. package/esm/typings/src/execution/{PromptResultUsage.d.ts → Usage.d.ts} +5 -5
  10. package/esm/typings/src/execution/utils/addUsage.d.ts +2 -2
  11. package/esm/typings/src/execution/utils/computeUsageCounts.d.ts +3 -3
  12. package/esm/typings/src/execution/utils/usage-constants.d.ts +77 -60
  13. package/esm/typings/src/execution/utils/usageToHuman.d.ts +5 -5
  14. package/esm/typings/src/execution/utils/usageToWorktime.d.ts +5 -5
  15. package/esm/typings/src/llm-providers/_common/utils/count-total-usage/LlmExecutionToolsWithTotalUsage.d.ts +9 -2
  16. package/esm/typings/src/llm-providers/_common/utils/count-total-usage/{countTotalUsage.d.ts → countUsage.d.ts} +1 -1
  17. package/esm/typings/src/llm-providers/_common/utils/count-total-usage/limitTotalUsage.d.ts +2 -2
  18. package/esm/typings/src/llm-providers/anthropic-claude/computeAnthropicClaudeUsage.d.ts +2 -2
  19. package/esm/typings/src/llm-providers/openai/OpenAiExecutionTools.d.ts +0 -9
  20. package/esm/typings/src/llm-providers/openai/computeOpenAiUsage.d.ts +2 -2
  21. package/esm/typings/src/pipeline/PipelineJson/PreparationJson.d.ts +2 -2
  22. package/esm/typings/src/playground/BrjappConnector.d.ts +67 -0
  23. package/esm/typings/src/playground/brjapp-api-schema.d.ts +12879 -0
  24. package/esm/typings/src/playground/playground.d.ts +5 -0
  25. package/esm/typings/src/remote-server/socket-types/_subtypes/PromptbookServer_Identification.d.ts +2 -1
  26. package/esm/typings/src/remote-server/types/RemoteServerOptions.d.ts +15 -3
  27. package/esm/typings/src/types/typeAliases.d.ts +8 -2
  28. package/package.json +1 -1
  29. package/umd/index.umd.js +210 -105
  30. package/umd/index.umd.js.map +1 -1
package/README.md CHANGED
@@ -23,6 +23,10 @@
23
23
 
24
24
 
25
25
 
26
+ <blockquote style="color: #ff8811">
27
+ <b>⚠ Warning:</b> This is a pre-release version of the library. It is not yet ready for production use. Please look at <a href="https://www.npmjs.com/package/@promptbook/core?activeTab=versions">latest stable release</a>.
28
+ </blockquote>
29
+
26
30
  ## 📦 Package `@promptbook/cli`
27
31
 
28
32
  - Promptbooks are [divided into several](#-packages) packages, all are published from [single monorepo](https://github.com/webgptorg/promptbook).
package/esm/index.es.js CHANGED
@@ -7,12 +7,12 @@ import { stat, access, constants, readFile, writeFile, readdir, mkdir, unlink, r
7
7
  import hexEncoder from 'crypto-js/enc-hex';
8
8
  import sha256 from 'crypto-js/sha256';
9
9
  import { randomBytes } from 'crypto';
10
+ import { Subject } from 'rxjs';
10
11
  import * as dotenv from 'dotenv';
11
12
  import { spawn } from 'child_process';
12
13
  import JSZip from 'jszip';
13
14
  import { format } from 'prettier';
14
15
  import parserHtml from 'prettier/parser-html';
15
- import { Subject } from 'rxjs';
16
16
  import { parse, unparse } from 'papaparse';
17
17
  import { SHA256 } from 'crypto-js';
18
18
  import { lookup, extension } from 'mime-types';
@@ -44,7 +44,7 @@ const BOOK_LANGUAGE_VERSION = '1.0.0';
44
44
  * @generated
45
45
  * @see https://github.com/webgptorg/promptbook
46
46
  */
47
- const PROMPTBOOK_ENGINE_VERSION = '0.88.0';
47
+ const PROMPTBOOK_ENGINE_VERSION = '0.89.0-2';
48
48
  /**
49
49
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
50
50
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -1679,30 +1679,42 @@ function cacheLlmTools(llmTools, options = {}) {
1679
1679
  * @@@ write how to combine multiple interceptors
1680
1680
  */
1681
1681
 
1682
+ /**
1683
+ * Represents the uncertain value
1684
+ *
1685
+ * @public exported from `@promptbook/core`
1686
+ */
1687
+ const ZERO_VALUE = $deepFreeze({ value: 0 });
1688
+ /**
1689
+ * Represents the uncertain value
1690
+ *
1691
+ * @public exported from `@promptbook/core`
1692
+ */
1693
+ const UNCERTAIN_ZERO_VALUE = $deepFreeze({ value: 0, isUncertain: true });
1682
1694
  /**
1683
1695
  * Represents the usage with no resources consumed
1684
1696
  *
1685
1697
  * @public exported from `@promptbook/core`
1686
1698
  */
1687
1699
  const ZERO_USAGE = $deepFreeze({
1688
- price: { value: 0 },
1700
+ price: ZERO_VALUE,
1689
1701
  input: {
1690
- tokensCount: { value: 0 },
1691
- charactersCount: { value: 0 },
1692
- wordsCount: { value: 0 },
1693
- sentencesCount: { value: 0 },
1694
- linesCount: { value: 0 },
1695
- paragraphsCount: { value: 0 },
1696
- pagesCount: { value: 0 },
1702
+ tokensCount: ZERO_VALUE,
1703
+ charactersCount: ZERO_VALUE,
1704
+ wordsCount: ZERO_VALUE,
1705
+ sentencesCount: ZERO_VALUE,
1706
+ linesCount: ZERO_VALUE,
1707
+ paragraphsCount: ZERO_VALUE,
1708
+ pagesCount: ZERO_VALUE,
1697
1709
  },
1698
1710
  output: {
1699
- tokensCount: { value: 0 },
1700
- charactersCount: { value: 0 },
1701
- wordsCount: { value: 0 },
1702
- sentencesCount: { value: 0 },
1703
- linesCount: { value: 0 },
1704
- paragraphsCount: { value: 0 },
1705
- pagesCount: { value: 0 },
1711
+ tokensCount: ZERO_VALUE,
1712
+ charactersCount: ZERO_VALUE,
1713
+ wordsCount: ZERO_VALUE,
1714
+ sentencesCount: ZERO_VALUE,
1715
+ linesCount: ZERO_VALUE,
1716
+ paragraphsCount: ZERO_VALUE,
1717
+ pagesCount: ZERO_VALUE,
1706
1718
  },
1707
1719
  });
1708
1720
  /**
@@ -1711,24 +1723,24 @@ const ZERO_USAGE = $deepFreeze({
1711
1723
  * @public exported from `@promptbook/core`
1712
1724
  */
1713
1725
  const UNCERTAIN_USAGE = $deepFreeze({
1714
- price: { value: 0, isUncertain: true },
1726
+ price: UNCERTAIN_ZERO_VALUE,
1715
1727
  input: {
1716
- tokensCount: { value: 0, isUncertain: true },
1717
- charactersCount: { value: 0, isUncertain: true },
1718
- wordsCount: { value: 0, isUncertain: true },
1719
- sentencesCount: { value: 0, isUncertain: true },
1720
- linesCount: { value: 0, isUncertain: true },
1721
- paragraphsCount: { value: 0, isUncertain: true },
1722
- pagesCount: { value: 0, isUncertain: true },
1728
+ tokensCount: UNCERTAIN_ZERO_VALUE,
1729
+ charactersCount: UNCERTAIN_ZERO_VALUE,
1730
+ wordsCount: UNCERTAIN_ZERO_VALUE,
1731
+ sentencesCount: UNCERTAIN_ZERO_VALUE,
1732
+ linesCount: UNCERTAIN_ZERO_VALUE,
1733
+ paragraphsCount: UNCERTAIN_ZERO_VALUE,
1734
+ pagesCount: UNCERTAIN_ZERO_VALUE,
1723
1735
  },
1724
1736
  output: {
1725
- tokensCount: { value: 0, isUncertain: true },
1726
- charactersCount: { value: 0, isUncertain: true },
1727
- wordsCount: { value: 0, isUncertain: true },
1728
- sentencesCount: { value: 0, isUncertain: true },
1729
- linesCount: { value: 0, isUncertain: true },
1730
- paragraphsCount: { value: 0, isUncertain: true },
1731
- pagesCount: { value: 0, isUncertain: true },
1737
+ tokensCount: UNCERTAIN_ZERO_VALUE,
1738
+ charactersCount: UNCERTAIN_ZERO_VALUE,
1739
+ wordsCount: UNCERTAIN_ZERO_VALUE,
1740
+ sentencesCount: UNCERTAIN_ZERO_VALUE,
1741
+ linesCount: UNCERTAIN_ZERO_VALUE,
1742
+ paragraphsCount: UNCERTAIN_ZERO_VALUE,
1743
+ pagesCount: UNCERTAIN_ZERO_VALUE,
1732
1744
  },
1733
1745
  });
1734
1746
  /**
@@ -1789,8 +1801,9 @@ function addUsage(...usageItems) {
1789
1801
  * @returns LLM tools with same functionality with added total cost counting
1790
1802
  * @public exported from `@promptbook/core`
1791
1803
  */
1792
- function countTotalUsage(llmTools) {
1804
+ function countUsage(llmTools) {
1793
1805
  let totalUsage = ZERO_USAGE;
1806
+ const spending = new Subject();
1794
1807
  const proxyTools = {
1795
1808
  get title() {
1796
1809
  // TODO: [🧠] Maybe put here some suffix
@@ -1800,12 +1813,15 @@ function countTotalUsage(llmTools) {
1800
1813
  // TODO: [🧠] Maybe put here some suffix
1801
1814
  return llmTools.description;
1802
1815
  },
1803
- async checkConfiguration() {
1816
+ checkConfiguration() {
1804
1817
  return /* not await */ llmTools.checkConfiguration();
1805
1818
  },
1806
1819
  listModels() {
1807
1820
  return /* not await */ llmTools.listModels();
1808
1821
  },
1822
+ spending() {
1823
+ return spending.asObservable();
1824
+ },
1809
1825
  getTotalUsage() {
1810
1826
  // <- Note: [🥫] Not using getter `get totalUsage` but `getTotalUsage` to allow this object to be proxied
1811
1827
  return totalUsage;
@@ -1816,6 +1832,7 @@ function countTotalUsage(llmTools) {
1816
1832
  // console.info('[🚕] callChatModel through countTotalUsage');
1817
1833
  const promptResult = await llmTools.callChatModel(prompt);
1818
1834
  totalUsage = addUsage(totalUsage, promptResult.usage);
1835
+ spending.next(promptResult.usage);
1819
1836
  return promptResult;
1820
1837
  };
1821
1838
  }
@@ -1824,6 +1841,7 @@ function countTotalUsage(llmTools) {
1824
1841
  // console.info('[🚕] callCompletionModel through countTotalUsage');
1825
1842
  const promptResult = await llmTools.callCompletionModel(prompt);
1826
1843
  totalUsage = addUsage(totalUsage, promptResult.usage);
1844
+ spending.next(promptResult.usage);
1827
1845
  return promptResult;
1828
1846
  };
1829
1847
  }
@@ -1832,6 +1850,7 @@ function countTotalUsage(llmTools) {
1832
1850
  // console.info('[🚕] callEmbeddingModel through countTotalUsage');
1833
1851
  const promptResult = await llmTools.callEmbeddingModel(prompt);
1834
1852
  totalUsage = addUsage(totalUsage, promptResult.usage);
1853
+ spending.next(promptResult.usage);
1835
1854
  return promptResult;
1836
1855
  };
1837
1856
  }
@@ -2404,6 +2423,7 @@ function joinLlmExecutionTools(...llmExecutionTools) {
2404
2423
  `);
2405
2424
  // TODO: [🟥] Detect browser / node and make it colorfull
2406
2425
  console.warn(warningMessage);
2426
+ // <- TODO: [🏮] Some standard way how to transform errors into warnings and how to handle non-critical fails during the tasks
2407
2427
  /*
2408
2428
  return {
2409
2429
  async listModels() {
@@ -2539,7 +2559,7 @@ async function $provideLlmToolsForWizzardOrCli(options) {
2539
2559
  throw new EnvironmentMismatchError('Function `$provideLlmToolsForWizzardOrCli` works only in Node.js environment');
2540
2560
  }
2541
2561
  const { isCacheReloaded } = options !== null && options !== void 0 ? options : {};
2542
- return cacheLlmTools(countTotalUsage(
2562
+ return cacheLlmTools(countUsage(
2543
2563
  // <- Note: for example here we don`t want the [🌯]
2544
2564
  await $provideLlmToolsFromEnv()), {
2545
2565
  storage: new FileCacheStorage({ fs: $provideFilesystemForNode() }, {
@@ -2697,6 +2717,7 @@ function $execCommand(options) {
2697
2717
  }
2698
2718
  else {
2699
2719
  console.warn(`Command "${humanReadableCommand}" exceeded time limit of ${timeout}ms but continues running`);
2720
+ // <- TODO: [🏮] Some standard way how to transform errors into warnings and how to handle non-critical fails during the tasks
2700
2721
  resolve('Command exceeded time limit');
2701
2722
  }
2702
2723
  });
@@ -2722,6 +2743,7 @@ function $execCommand(options) {
2722
2743
  output.push(stderr.toString());
2723
2744
  if (isVerbose && stderr.toString().trim()) {
2724
2745
  console.warn(stderr.toString());
2746
+ // <- TODO: [🏮] Some standard way how to transform errors into warnings and how to handle non-critical fails during the tasks
2725
2747
  }
2726
2748
  });
2727
2749
  const finishWithCode = (code) => {
@@ -2733,6 +2755,7 @@ function $execCommand(options) {
2733
2755
  else {
2734
2756
  if (isVerbose) {
2735
2757
  console.warn(`Command "${humanReadableCommand}" exited with code ${code}`);
2758
+ // <- TODO: [🏮] Some standard way how to transform errors into warnings and how to handle non-critical fails during the tasks
2736
2759
  }
2737
2760
  resolve(spaceTrim$1(output.join('\n')));
2738
2761
  }
@@ -2754,6 +2777,7 @@ function $execCommand(options) {
2754
2777
  else {
2755
2778
  if (isVerbose) {
2756
2779
  console.warn(error);
2780
+ // <- TODO: [🏮] Some standard way how to transform errors into warnings and how to handle non-critical fails during the tasks
2757
2781
  }
2758
2782
  resolve(spaceTrim$1(output.join('\n')));
2759
2783
  }
@@ -4307,6 +4331,7 @@ function assertsTaskSuccessful(executionResult) {
4307
4331
  const { isSuccessful, errors, warnings } = executionResult;
4308
4332
  for (const warning of warnings) {
4309
4333
  console.warn(warning.message);
4334
+ // <- TODO: [🏮] Some standard way how to transform errors into warnings and how to handle non-critical fails during the tasks
4310
4335
  }
4311
4336
  if (isSuccessful === true) {
4312
4337
  return;
@@ -4648,7 +4673,7 @@ function extractParameterNamesFromTask(task) {
4648
4673
  if (parameterNames.has(subparameterName)) {
4649
4674
  parameterNames.delete(subparameterName);
4650
4675
  parameterNames.add(foreach.parameterName);
4651
- // <- TODO: [🚎] Warn/logic error when `subparameterName` not used
4676
+ // <- TODO: [🏮] Warn/logic error when `subparameterName` not used
4652
4677
  }
4653
4678
  }
4654
4679
  }
@@ -6263,6 +6288,7 @@ function createPipelineExecutor(options) {
6263
6288
 
6264
6289
  @see more at https://ptbk.io/prepare-pipeline
6265
6290
  `));
6291
+ // <- TODO: [🏮] Some standard way how to transform errors into warnings and how to handle non-critical fails during the tasks
6266
6292
  }
6267
6293
  let runCount = 0;
6268
6294
  const pipelineExecutorWithCallback = async (inputParameters, onProgress) => {
@@ -6605,63 +6631,73 @@ async function prepareKnowledgePieces(knowledgeSources, tools, options) {
6605
6631
  const { maxParallelCount = DEFAULT_MAX_PARALLEL_COUNT, rootDirname, isVerbose = DEFAULT_IS_VERBOSE } = options;
6606
6632
  const knowledgePreparedUnflatten = new Array(knowledgeSources.length);
6607
6633
  await forEachAsync(knowledgeSources, { maxParallelCount }, async (knowledgeSource, index) => {
6608
- let partialPieces = null;
6609
- const sourceHandler = await makeKnowledgeSourceHandler(knowledgeSource, tools, { rootDirname, isVerbose });
6610
- const scrapers = arrayableToArray(tools.scrapers);
6611
- for (const scraper of scrapers) {
6612
- if (!scraper.metadata.mimeTypes.includes(sourceHandler.mimeType)
6613
- // <- TODO: [🦔] Implement mime-type wildcards
6614
- ) {
6615
- continue;
6616
- }
6617
- const partialPiecesUnchecked = await scraper.scrape(sourceHandler);
6618
- if (partialPiecesUnchecked !== null) {
6619
- partialPieces = [...partialPiecesUnchecked];
6620
- // <- TODO: [🪓] Here should be no need for spreading new array, just `partialPieces = partialPiecesUnchecked`
6621
- break;
6622
- }
6623
- console.warn(spaceTrim((block) => `
6624
- Cannot scrape knowledge from source despite the scraper \`${scraper.metadata.className}\` supports the mime type "${sourceHandler.mimeType}".
6634
+ try {
6635
+ let partialPieces = null;
6636
+ const sourceHandler = await makeKnowledgeSourceHandler(knowledgeSource, tools, { rootDirname, isVerbose });
6637
+ const scrapers = arrayableToArray(tools.scrapers);
6638
+ for (const scraper of scrapers) {
6639
+ if (!scraper.metadata.mimeTypes.includes(sourceHandler.mimeType)
6640
+ // <- TODO: [🦔] Implement mime-type wildcards
6641
+ ) {
6642
+ continue;
6643
+ }
6644
+ const partialPiecesUnchecked = await scraper.scrape(sourceHandler);
6645
+ if (partialPiecesUnchecked !== null) {
6646
+ partialPieces = [...partialPiecesUnchecked];
6647
+ // <- TODO: [🪓] Here should be no need for spreading new array, just `partialPieces = partialPiecesUnchecked`
6648
+ break;
6649
+ }
6650
+ console.warn(spaceTrim((block) => `
6651
+ Cannot scrape knowledge from source despite the scraper \`${scraper.metadata.className}\` supports the mime type "${sourceHandler.mimeType}".
6625
6652
 
6626
- The source:
6627
- ${block(knowledgeSource.knowledgeSourceContent
6628
- .split('\n')
6629
- .map((line) => `> ${line}`)
6630
- .join('\n'))}
6653
+ The source:
6654
+ ${block(knowledgeSource.knowledgeSourceContent
6655
+ .split('\n')
6656
+ .map((line) => `> ${line}`)
6657
+ .join('\n'))}
6631
6658
 
6632
- ${block($registeredScrapersMessage(scrapers))}
6659
+ ${block($registeredScrapersMessage(scrapers))}
6633
6660
 
6634
6661
 
6635
- `));
6636
- }
6637
- if (partialPieces === null) {
6638
- throw new KnowledgeScrapeError(spaceTrim((block) => `
6639
- Cannot scrape knowledge
6662
+ `));
6663
+ // <- TODO: [🏮] Some standard way how to transform errors into warnings and how to handle non-critical fails during the tasks
6664
+ }
6665
+ if (partialPieces === null) {
6666
+ throw new KnowledgeScrapeError(spaceTrim((block) => `
6667
+ Cannot scrape knowledge
6640
6668
 
6641
- The source:
6642
- > ${block(knowledgeSource.knowledgeSourceContent
6643
- .split('\n')
6644
- .map((line) => `> ${line}`)
6645
- .join('\n'))}
6669
+ The source:
6670
+ > ${block(knowledgeSource.knowledgeSourceContent
6671
+ .split('\n')
6672
+ .map((line) => `> ${line}`)
6673
+ .join('\n'))}
6646
6674
 
6647
- No scraper found for the mime type "${sourceHandler.mimeType}"
6675
+ No scraper found for the mime type "${sourceHandler.mimeType}"
6648
6676
 
6649
- ${block($registeredScrapersMessage(scrapers))}
6677
+ ${block($registeredScrapersMessage(scrapers))}
6650
6678
 
6651
6679
 
6652
- `));
6680
+ `));
6681
+ }
6682
+ const pieces = partialPieces.map((partialPiece) => ({
6683
+ ...partialPiece,
6684
+ sources: [
6685
+ {
6686
+ name: knowledgeSource.name,
6687
+ // line, column <- TODO: [☀]
6688
+ // <- TODO: [❎]
6689
+ },
6690
+ ],
6691
+ }));
6692
+ knowledgePreparedUnflatten[index] = pieces;
6693
+ }
6694
+ catch (error) {
6695
+ if (!(error instanceof Error)) {
6696
+ throw error;
6697
+ }
6698
+ console.warn(error);
6699
+ // <- TODO: [🏮] Some standard way how to transform errors into warnings and how to handle non-critical fails during the tasks
6653
6700
  }
6654
- const pieces = partialPieces.map((partialPiece) => ({
6655
- ...partialPiece,
6656
- sources: [
6657
- {
6658
- name: knowledgeSource.name,
6659
- // line, column <- TODO: [☀]
6660
- // <- TODO: [❎]
6661
- },
6662
- ],
6663
- }));
6664
- knowledgePreparedUnflatten[index] = pieces;
6665
6701
  });
6666
6702
  const knowledgePrepared = knowledgePreparedUnflatten.flat();
6667
6703
  return knowledgePrepared;
@@ -6767,7 +6803,7 @@ async function preparePipeline(pipeline, tools, options) {
6767
6803
  // TODO: [🚐] Make arrayable LLMs -> single LLM DRY
6768
6804
  const _llms = arrayableToArray(tools.llm);
6769
6805
  const llmTools = _llms.length === 1 ? _llms[0] : joinLlmExecutionTools(..._llms);
6770
- const llmToolsWithUsage = countTotalUsage(llmTools);
6806
+ const llmToolsWithUsage = countUsage(llmTools);
6771
6807
  // <- TODO: [🌯]
6772
6808
  /*
6773
6809
  TODO: [🧠][🪑][🔃] Should this be done or not
@@ -8486,7 +8522,8 @@ const modelCommandParser = {
8486
8522
  if ($pipelineJson.defaultModelRequirements[command.key] !== undefined) {
8487
8523
  if ($pipelineJson.defaultModelRequirements[command.key] === command.value) {
8488
8524
  console.warn(`Multiple commands \`MODEL ${command.key} ${command.value}\` in the pipeline head`);
8489
- // <- TODO: [🚎][💩] Some better way how to get warnings from pipeline parsing / logic
8525
+ // <- TODO: [🏮] Some better way how to get warnings from pipeline parsing / logic
8526
+ // <- TODO: [🏮] Some standard way how to transform errors into warnings and how to handle non-critical fails during the tasks
8490
8527
  }
8491
8528
  else {
8492
8529
  throw new ParseError(spaceTrim(`
@@ -8518,6 +8555,7 @@ const modelCommandParser = {
8518
8555
  modelVariant: 'VARIANT',
8519
8556
  maxTokens: '???',
8520
8557
  }[command.key]} ${command.value}\` in the task "${$taskJson.title || $taskJson.name}"`);
8558
+ // <- TODO: [🏮] Some standard way how to transform errors into warnings and how to handle non-critical fails during the tasks
8521
8559
  }
8522
8560
  else {
8523
8561
  throw new ParseError(spaceTrim(`
@@ -8797,15 +8835,15 @@ function $applyToTaskJson(command, $taskJson, $pipelineJson) {
8797
8835
  }
8798
8836
  console.warn(spaceTrim(`
8799
8837
 
8800
- Persona "${personaName}" is defined multiple times with different description:
8838
+ Persona "${personaName}" is defined multiple times with different description:
8801
8839
 
8802
- First definition:
8803
- ${persona.description}
8840
+ First definition:
8841
+ ${persona.description}
8804
8842
 
8805
- Second definition:
8806
- ${personaDescription}
8843
+ Second definition:
8844
+ ${personaDescription}
8807
8845
 
8808
- `));
8846
+ `));
8809
8847
  persona.description += spaceTrim('\n\n' + personaDescription);
8810
8848
  }
8811
8849
 
@@ -11436,6 +11474,7 @@ function $initializeMakeCommand(program) {
11436
11474
  : join(path, `${DEFAULT_PIPELINE_COLLECTION_BASE_FILENAME}.${extension}`);
11437
11475
  if (!output.endsWith(`.${extension}`)) {
11438
11476
  console.warn(colors.yellow(`Warning: Extension of output file should be "${extension}"`));
11477
+ // <- TODO: [🏮] Some standard way how to transform errors into warnings and how to handle non-critical fails during the tasks
11439
11478
  }
11440
11479
  await mkdir(dirname(filename), { recursive: true });
11441
11480
  if (typeof content === 'string') {
@@ -11536,6 +11575,7 @@ function $initializeMakeCommand(program) {
11536
11575
  }
11537
11576
  if (formats.length > 0) {
11538
11577
  console.warn(colors.yellow(`Format ${formats.join(' and ')} is not supported`));
11578
+ // <- TODO: [🏮] Some standard way how to transform errors into warnings and how to handle non-critical fails during the tasks
11539
11579
  }
11540
11580
  console.info(colors.green(`Collection builded successfully`));
11541
11581
  if (isVerbose) {
@@ -11582,7 +11622,8 @@ function addAutoGeneratedSection(content, options) {
11582
11622
  `));
11583
11623
  }
11584
11624
  console.warn(`No place where to put the section <!--${sectionName}-->, using the end of the file`);
11585
- // <- TODO: [🚎][💩] Some better way how to get warnings from pipeline parsing / logic
11625
+ // <- TODO: [🏮] Some standard way how to transform errors into warnings and how to handle non-critical fails during the tasks
11626
+ // <- TODO: [🏮] Some better way how to get warnings from pipeline parsing / logic
11586
11627
  return spaceTrim$1((block) => `
11587
11628
  ${block(content)}
11588
11629
 
@@ -12632,6 +12673,7 @@ function startRemoteServer(options) {
12632
12673
  https://github.com/webgptorg/promptbook
12633
12674
  `));
12634
12675
  });
12676
+ // TODO: !!!!!! Add login route
12635
12677
  app.get(`${rootPath}/books`, async (request, response) => {
12636
12678
  if (collection === null) {
12637
12679
  response.status(500).send('No collection available');
@@ -12965,6 +13007,7 @@ function $initializeStartServerCommand(program) {
12965
13007
  const url = !rawUrl ? null : new URL(rawUrl);
12966
13008
  if (url !== null && url.port !== port.toString()) {
12967
13009
  console.warn(colors.yellow(`Port in --url is different from --port which the server will listen on, this is ok only if you proxy from one port to another, for exaple via nginx or docker`));
13010
+ // <- TODO: [🏮] Some standard way how to transform errors into warnings and how to handle non-critical fails during the tasks
12968
13011
  }
12969
13012
  let rootUrl = undefined;
12970
13013
  if (url !== null) {
@@ -13110,6 +13153,58 @@ function $initializeTestCommand(program) {
13110
13153
  * Note: This is named "test-command.ts" to avoid name collision with jest unit test files
13111
13154
  */
13112
13155
 
13156
+ /**
13157
+ * Initializes `login` command for Promptbook CLI utilities
13158
+ *
13159
+ * Note: `$` is used to indicate that this function is not a pure function - it registers a command in the CLI
13160
+ *
13161
+ * @private internal function of `promptbookCli`
13162
+ */
13163
+ function $initializeLoginCommand(program) {
13164
+ const loginCommand = program.command('login');
13165
+ loginCommand.description(spaceTrim(`
13166
+ Login to the remote Promptbook server
13167
+ `));
13168
+ loginCommand.action(handleActionErrors(async () => {
13169
+ // @@@
13170
+ console.error(colors.green(spaceTrim(`
13171
+ You will be logged in to https://promptbook.studio server.
13172
+ If you don't have an account, it will be created automatically.
13173
+ `)));
13174
+ const { email, password } = await prompts([
13175
+ {
13176
+ type: 'text',
13177
+ name: 'email',
13178
+ message: 'Enter your email:',
13179
+ validate: (value) => (isValidEmail(value) ? true : 'Valid email is required'),
13180
+ },
13181
+ {
13182
+ type: 'password',
13183
+ name: 'password',
13184
+ message: 'Enter your password:',
13185
+ validate: (value) => value.length /* <- TODO: [🧠] Better password validation */ > 0 ? true : 'Password is required',
13186
+ },
13187
+ ]);
13188
+ TODO_USE(email, password);
13189
+ await forTime(1000);
13190
+ console.error(colors.green(spaceTrim(`
13191
+ Your account ${email} was successfully created.
13192
+
13193
+ Please verify your email:
13194
+ https://brj.app/api/v1/customer/register-account?apiKey=PRODdh003eNKaec7PoO1AzU244tsL4WO
13195
+
13196
+ After verification, you will receive 500 000 credits for free 🎉
13197
+ `)));
13198
+ return process.exit(0);
13199
+ }));
13200
+ }
13201
+ /**
13202
+ * TODO: Pass remote server URL (and path)
13203
+ * TODO: Implement non-interactive login
13204
+ * Note: [💞] Ignore a discrepancy between file name and entity name
13205
+ * Note: [🟡] Code in this file should never be published outside of `@promptbook/cli`
13206
+ */
13207
+
13113
13208
  /**
13114
13209
  * Runs CLI utilities of Promptbook package
13115
13210
  *
@@ -13136,6 +13231,7 @@ async function promptbookCli() {
13136
13231
  program.description(CLAIM);
13137
13232
  $initializeAboutCommand(program);
13138
13233
  $initializeRunCommand(program);
13234
+ $initializeLoginCommand(program);
13139
13235
  $initializeHelloCommand(program);
13140
13236
  $initializeMakeCommand(program);
13141
13237
  $initializePrettifyCommand(program);
@@ -13456,7 +13552,7 @@ const ANTHROPIC_CLAUDE_MODELS = exportJson({
13456
13552
  * Helper of usage compute
13457
13553
  *
13458
13554
  * @param content the content of prompt or response
13459
- * @returns part of PromptResultUsageCounts
13555
+ * @returns part of UsageCounts
13460
13556
  *
13461
13557
  * @private internal utility of LlmExecutionTools
13462
13558
  */
@@ -13480,7 +13576,7 @@ function computeUsageCounts(content) {
13480
13576
  */
13481
13577
  function uncertainNumber(value) {
13482
13578
  if (value === null || value === undefined || Number.isNaN(value)) {
13483
- return { value: 0, isUncertain: true };
13579
+ return UNCERTAIN_ZERO_VALUE;
13484
13580
  }
13485
13581
  return { value };
13486
13582
  }
@@ -13717,7 +13813,7 @@ class AnthropicClaudeExecutionTools {
13717
13813
  const resultContent = rawResponse.choices[0].text;
13718
13814
  // eslint-disable-next-line prefer-const
13719
13815
  complete = $getCurrentDate();
13720
- const usage = { price: 'UNKNOWN', inputTokens: 0, outputTokens: 0 /* <- TODO: [🐞] Compute usage * / } satisfies PromptResultUsage;
13816
+ const usage = { price: 'UNKNOWN', inputTokens: 0, outputTokens: 0 /* <- TODO: [🐞] Compute usage * / } satisfies Usage;
13721
13817
 
13722
13818
 
13723
13819
 
@@ -14813,11 +14909,17 @@ function createExecutionToolsFromVercelProvider(options) {
14813
14909
  throw new PipelineExecutionError('No response message');
14814
14910
  }
14815
14911
  const complete = $getCurrentDate();
14816
- /*
14817
- TODO: [🕘] Usage count
14818
- const usage = computeOpenAiUsage(content || '', resultContent || '', rawResponse);
14819
- */
14820
- const usage = UNCERTAIN_USAGE;
14912
+ const usage = {
14913
+ price: UNCERTAIN_ZERO_VALUE,
14914
+ input: {
14915
+ tokensCount: uncertainNumber(rawResponse.usage.promptTokens),
14916
+ ...computeUsageCounts(rawPromptContent),
14917
+ },
14918
+ output: {
14919
+ tokensCount: uncertainNumber(rawResponse.usage.completionTokens),
14920
+ ...computeUsageCounts(rawResponse.text),
14921
+ },
14922
+ };
14821
14923
  return exportJson({
14822
14924
  name: 'promptResult',
14823
14925
  message: `Result of \`createExecutionToolsFromVercelProvider.callChatModel\``,
@@ -15170,15 +15272,18 @@ class OpenAiExecutionTools {
15170
15272
  }
15171
15273
  return this.client;
15172
15274
  }
15275
+ /*
15276
+ Note: Commenting this out to avoid circular dependency
15173
15277
  /**
15174
15278
  * Create (sub)tools for calling OpenAI API Assistants
15175
15279
  *
15176
15280
  * @param assistantId Which assistant to use
15177
15281
  * @returns Tools for calling OpenAI API Assistants with same token
15178
- */
15179
- createAssistantSubtools(assistantId) {
15282
+ * /
15283
+ public createAssistantSubtools(assistantId: string_token): OpenAiAssistantExecutionTools {
15180
15284
  return new OpenAiAssistantExecutionTools({ ...this.options, assistantId });
15181
15285
  }
15286
+ */
15182
15287
  /**
15183
15288
  * Check the `options` passed to `constructor`
15184
15289
  */