@promptbook/remote-server 0.89.0-1 → 0.89.0-11

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 (52) hide show
  1. package/README.md +3 -1
  2. package/esm/index.es.js +365 -95
  3. package/esm/index.es.js.map +1 -1
  4. package/esm/typings/src/_packages/core.index.d.ts +16 -4
  5. package/esm/typings/src/_packages/remote-client.index.d.ts +6 -8
  6. package/esm/typings/src/_packages/remote-server.index.d.ts +6 -6
  7. package/esm/typings/src/_packages/types.index.d.ts +18 -20
  8. package/esm/typings/src/cli/cli-commands/login.d.ts +15 -0
  9. package/esm/typings/src/cli/common/$addGlobalOptionsToCommand.d.ts +7 -0
  10. package/esm/typings/src/cli/common/$provideLlmToolsForCli.d.ts +15 -0
  11. package/esm/typings/src/config.d.ts +15 -8
  12. package/esm/typings/src/errors/0-index.d.ts +6 -0
  13. package/esm/typings/src/errors/AuthenticationError.d.ts +9 -0
  14. package/esm/typings/src/errors/PromptbookFetchError.d.ts +9 -0
  15. package/esm/typings/src/execution/PipelineExecutorResult.d.ts +2 -2
  16. package/esm/typings/src/execution/PromptResult.d.ts +2 -2
  17. package/esm/typings/src/execution/{PromptResultUsage.d.ts → Usage.d.ts} +5 -5
  18. package/esm/typings/src/execution/utils/addUsage.d.ts +2 -2
  19. package/esm/typings/src/execution/utils/computeUsageCounts.d.ts +3 -3
  20. package/esm/typings/src/execution/utils/usage-constants.d.ts +77 -60
  21. package/esm/typings/src/execution/utils/usageToHuman.d.ts +5 -5
  22. package/esm/typings/src/execution/utils/usageToWorktime.d.ts +5 -5
  23. package/esm/typings/src/llm-providers/_common/register/$provideEnvFilename.d.ts +12 -0
  24. package/esm/typings/src/llm-providers/_common/register/$provideLlmToolsConfigurationFromEnv.d.ts +2 -8
  25. package/esm/typings/src/llm-providers/_common/register/$provideLlmToolsForTestingAndScriptsAndPlayground.d.ts +2 -0
  26. package/esm/typings/src/llm-providers/_common/register/$provideLlmToolsForWizzardOrCli.d.ts +36 -1
  27. package/esm/typings/src/llm-providers/_common/register/$provideLlmToolsFromEnv.d.ts +1 -0
  28. package/esm/typings/src/llm-providers/_common/utils/count-total-usage/LlmExecutionToolsWithTotalUsage.d.ts +3 -3
  29. package/esm/typings/src/llm-providers/_common/utils/count-total-usage/limitTotalUsage.d.ts +2 -2
  30. package/esm/typings/src/llm-providers/anthropic-claude/AnthropicClaudeExecutionToolsOptions.d.ts +1 -1
  31. package/esm/typings/src/llm-providers/anthropic-claude/computeAnthropicClaudeUsage.d.ts +2 -2
  32. package/esm/typings/src/llm-providers/anthropic-claude/register-configuration.d.ts +1 -1
  33. package/esm/typings/src/llm-providers/openai/OpenAiExecutionTools.d.ts +0 -9
  34. package/esm/typings/src/llm-providers/openai/computeOpenAiUsage.d.ts +2 -2
  35. package/esm/typings/src/pipeline/PipelineJson/PreparationJson.d.ts +2 -2
  36. package/esm/typings/src/remote-server/RemoteServer.d.ts +23 -0
  37. package/esm/typings/src/remote-server/socket-types/_subtypes/{PromptbookServer_Identification.d.ts → Identification.d.ts} +3 -3
  38. package/esm/typings/src/remote-server/socket-types/listModels/PromptbookServer_ListModels_Request.d.ts +2 -2
  39. package/esm/typings/src/remote-server/socket-types/prepare/PromptbookServer_PreparePipeline_Request.d.ts +2 -2
  40. package/esm/typings/src/remote-server/socket-types/prompt/PromptbookServer_Prompt_Request.d.ts +2 -2
  41. package/esm/typings/src/remote-server/startRemoteServer.d.ts +2 -2
  42. package/esm/typings/src/remote-server/types/RemoteClientOptions.d.ts +4 -12
  43. package/esm/typings/src/remote-server/types/RemoteServerOptions.d.ts +73 -3
  44. package/esm/typings/src/scrapers/_common/utils/{scraperFetch.d.ts → promptbookFetch.d.ts} +2 -2
  45. package/esm/typings/src/storage/env-storage/$EnvStorage.d.ts +37 -0
  46. package/esm/typings/src/types/typeAliases.d.ts +6 -0
  47. package/esm/typings/src/utils/organization/TODO_narrow.d.ts +6 -0
  48. package/package.json +4 -2
  49. package/umd/index.umd.js +369 -99
  50. package/umd/index.umd.js.map +1 -1
  51. package/esm/typings/src/playground/BrjappConnector.d.ts +0 -64
  52. package/esm/typings/src/playground/brjapp-api-schema.d.ts +0 -12879
package/esm/index.es.js CHANGED
@@ -3,6 +3,8 @@ import express from 'express';
3
3
  import http from 'http';
4
4
  import { Server } from 'socket.io';
5
5
  import spaceTrim$1, { spaceTrim } from 'spacetrim';
6
+ import swaggerJsdoc from 'swagger-jsdoc';
7
+ import swaggerUi from 'swagger-ui-express';
6
8
  import { forTime } from 'waitasecond';
7
9
  import { randomBytes } from 'crypto';
8
10
  import { spawn } from 'child_process';
@@ -31,7 +33,7 @@ const BOOK_LANGUAGE_VERSION = '1.0.0';
31
33
  * @generated
32
34
  * @see https://github.com/webgptorg/promptbook
33
35
  */
34
- const PROMPTBOOK_ENGINE_VERSION = '0.89.0-1';
36
+ const PROMPTBOOK_ENGINE_VERSION = '0.89.0-11';
35
37
  /**
36
38
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
37
39
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -156,6 +158,7 @@ const DEFAULT_MAX_PARALLEL_COUNT = 5; // <- TODO: [🤹‍♂️]
156
158
  */
157
159
  const DEFAULT_MAX_EXECUTION_ATTEMPTS = 10; // <- TODO: [🤹‍♂️]
158
160
  // <- TODO: [🕝] Make also `BOOKS_DIRNAME_ALTERNATIVES`
161
+ // TODO: !!!!!! Just .promptbook dir, hardocode others
159
162
  /**
160
163
  * Where to store the temporary downloads
161
164
  *
@@ -207,9 +210,22 @@ const IS_PIPELINE_LOGIC_VALIDATED = just(
207
210
  true);
208
211
  /**
209
212
  * Note: [💞] Ignore a discrepancy between file name and entity name
210
- * TODO: [🧠][🧜‍♂️] Maybe join remoteUrl and path into single value
213
+ * TODO: [🧠][🧜‍♂️] Maybe join remoteServerUrl and path into single value
211
214
  */
212
215
 
216
+ /**
217
+ * AuthenticationError is thrown from login function which is dependency of remote server
218
+ *
219
+ * @public exported from `@promptbook/core`
220
+ */
221
+ class AuthenticationError extends Error {
222
+ constructor(message) {
223
+ super(message);
224
+ this.name = 'AuthenticationError';
225
+ Object.setPrototypeOf(this, AuthenticationError.prototype);
226
+ }
227
+ }
228
+
213
229
  /**
214
230
  * Generates random token
215
231
  *
@@ -438,6 +454,19 @@ class PipelineUrlError extends Error {
438
454
  }
439
455
  }
440
456
 
457
+ /**
458
+ * Error thrown when a fetch request fails
459
+ *
460
+ * @public exported from `@promptbook/core`
461
+ */
462
+ class PromptbookFetchError extends Error {
463
+ constructor(message) {
464
+ super(message);
465
+ this.name = 'PromptbookFetchError';
466
+ Object.setPrototypeOf(this, PromptbookFetchError.prototype);
467
+ }
468
+ }
469
+
441
470
  /**
442
471
  * Make error report URL for the given error
443
472
  *
@@ -543,6 +572,8 @@ const COMMON_JAVASCRIPT_ERRORS = {
543
572
  TypeError,
544
573
  URIError,
545
574
  AggregateError,
575
+ AuthenticationError,
576
+ PromptbookFetchError,
546
577
  /*
547
578
  Note: Not widely supported
548
579
  > InternalError,
@@ -578,6 +609,10 @@ function serializeError(error) {
578
609
 
579
610
  Cannot serialize error with name "${name}"
580
611
 
612
+ Authors of Promptbook probably forgot to add this error into the list of errors:
613
+ https://github.com/webgptorg/promptbook/blob/main/src/errors/0-index.ts
614
+
615
+
581
616
  ${block(stack || message)}
582
617
 
583
618
  `));
@@ -694,6 +729,7 @@ function $execCommand(options) {
694
729
  }
695
730
  else {
696
731
  console.warn(`Command "${humanReadableCommand}" exceeded time limit of ${timeout}ms but continues running`);
732
+ // <- TODO: [🏮] Some standard way how to transform errors into warnings and how to handle non-critical fails during the tasks
697
733
  resolve('Command exceeded time limit');
698
734
  }
699
735
  });
@@ -719,6 +755,7 @@ function $execCommand(options) {
719
755
  output.push(stderr.toString());
720
756
  if (isVerbose && stderr.toString().trim()) {
721
757
  console.warn(stderr.toString());
758
+ // <- TODO: [🏮] Some standard way how to transform errors into warnings and how to handle non-critical fails during the tasks
722
759
  }
723
760
  });
724
761
  const finishWithCode = (code) => {
@@ -730,6 +767,7 @@ function $execCommand(options) {
730
767
  else {
731
768
  if (isVerbose) {
732
769
  console.warn(`Command "${humanReadableCommand}" exited with code ${code}`);
770
+ // <- TODO: [🏮] Some standard way how to transform errors into warnings and how to handle non-critical fails during the tasks
733
771
  }
734
772
  resolve(spaceTrim(output.join('\n')));
735
773
  }
@@ -751,6 +789,7 @@ function $execCommand(options) {
751
789
  else {
752
790
  if (isVerbose) {
753
791
  console.warn(error);
792
+ // <- TODO: [🏮] Some standard way how to transform errors into warnings and how to handle non-critical fails during the tasks
754
793
  }
755
794
  resolve(spaceTrim(output.join('\n')));
756
795
  }
@@ -1819,6 +1858,7 @@ function assertsTaskSuccessful(executionResult) {
1819
1858
  const { isSuccessful, errors, warnings } = executionResult;
1820
1859
  for (const warning of warnings) {
1821
1860
  console.warn(warning.message);
1861
+ // <- TODO: [🏮] Some standard way how to transform errors into warnings and how to handle non-critical fails during the tasks
1822
1862
  }
1823
1863
  if (isSuccessful === true) {
1824
1864
  return;
@@ -2420,30 +2460,42 @@ async function forEachAsync(array, options, callbackfunction) {
2420
2460
  await Promise.all(tasks);
2421
2461
  }
2422
2462
 
2463
+ /**
2464
+ * Represents the uncertain value
2465
+ *
2466
+ * @public exported from `@promptbook/core`
2467
+ */
2468
+ const ZERO_VALUE = $deepFreeze({ value: 0 });
2469
+ /**
2470
+ * Represents the uncertain value
2471
+ *
2472
+ * @public exported from `@promptbook/core`
2473
+ */
2474
+ const UNCERTAIN_ZERO_VALUE = $deepFreeze({ value: 0, isUncertain: true });
2423
2475
  /**
2424
2476
  * Represents the usage with no resources consumed
2425
2477
  *
2426
2478
  * @public exported from `@promptbook/core`
2427
2479
  */
2428
2480
  const ZERO_USAGE = $deepFreeze({
2429
- price: { value: 0 },
2481
+ price: ZERO_VALUE,
2430
2482
  input: {
2431
- tokensCount: { value: 0 },
2432
- charactersCount: { value: 0 },
2433
- wordsCount: { value: 0 },
2434
- sentencesCount: { value: 0 },
2435
- linesCount: { value: 0 },
2436
- paragraphsCount: { value: 0 },
2437
- pagesCount: { value: 0 },
2483
+ tokensCount: ZERO_VALUE,
2484
+ charactersCount: ZERO_VALUE,
2485
+ wordsCount: ZERO_VALUE,
2486
+ sentencesCount: ZERO_VALUE,
2487
+ linesCount: ZERO_VALUE,
2488
+ paragraphsCount: ZERO_VALUE,
2489
+ pagesCount: ZERO_VALUE,
2438
2490
  },
2439
2491
  output: {
2440
- tokensCount: { value: 0 },
2441
- charactersCount: { value: 0 },
2442
- wordsCount: { value: 0 },
2443
- sentencesCount: { value: 0 },
2444
- linesCount: { value: 0 },
2445
- paragraphsCount: { value: 0 },
2446
- pagesCount: { value: 0 },
2492
+ tokensCount: ZERO_VALUE,
2493
+ charactersCount: ZERO_VALUE,
2494
+ wordsCount: ZERO_VALUE,
2495
+ sentencesCount: ZERO_VALUE,
2496
+ linesCount: ZERO_VALUE,
2497
+ paragraphsCount: ZERO_VALUE,
2498
+ pagesCount: ZERO_VALUE,
2447
2499
  },
2448
2500
  });
2449
2501
  /**
@@ -2452,24 +2504,24 @@ const ZERO_USAGE = $deepFreeze({
2452
2504
  * @public exported from `@promptbook/core`
2453
2505
  */
2454
2506
  $deepFreeze({
2455
- price: { value: 0, isUncertain: true },
2507
+ price: UNCERTAIN_ZERO_VALUE,
2456
2508
  input: {
2457
- tokensCount: { value: 0, isUncertain: true },
2458
- charactersCount: { value: 0, isUncertain: true },
2459
- wordsCount: { value: 0, isUncertain: true },
2460
- sentencesCount: { value: 0, isUncertain: true },
2461
- linesCount: { value: 0, isUncertain: true },
2462
- paragraphsCount: { value: 0, isUncertain: true },
2463
- pagesCount: { value: 0, isUncertain: true },
2509
+ tokensCount: UNCERTAIN_ZERO_VALUE,
2510
+ charactersCount: UNCERTAIN_ZERO_VALUE,
2511
+ wordsCount: UNCERTAIN_ZERO_VALUE,
2512
+ sentencesCount: UNCERTAIN_ZERO_VALUE,
2513
+ linesCount: UNCERTAIN_ZERO_VALUE,
2514
+ paragraphsCount: UNCERTAIN_ZERO_VALUE,
2515
+ pagesCount: UNCERTAIN_ZERO_VALUE,
2464
2516
  },
2465
2517
  output: {
2466
- tokensCount: { value: 0, isUncertain: true },
2467
- charactersCount: { value: 0, isUncertain: true },
2468
- wordsCount: { value: 0, isUncertain: true },
2469
- sentencesCount: { value: 0, isUncertain: true },
2470
- linesCount: { value: 0, isUncertain: true },
2471
- paragraphsCount: { value: 0, isUncertain: true },
2472
- pagesCount: { value: 0, isUncertain: true },
2518
+ tokensCount: UNCERTAIN_ZERO_VALUE,
2519
+ charactersCount: UNCERTAIN_ZERO_VALUE,
2520
+ wordsCount: UNCERTAIN_ZERO_VALUE,
2521
+ sentencesCount: UNCERTAIN_ZERO_VALUE,
2522
+ linesCount: UNCERTAIN_ZERO_VALUE,
2523
+ paragraphsCount: UNCERTAIN_ZERO_VALUE,
2524
+ pagesCount: UNCERTAIN_ZERO_VALUE,
2473
2525
  },
2474
2526
  });
2475
2527
  /**
@@ -2757,6 +2809,7 @@ function joinLlmExecutionTools(...llmExecutionTools) {
2757
2809
  `);
2758
2810
  // TODO: [🟥] Detect browser / node and make it colorfull
2759
2811
  console.warn(warningMessage);
2812
+ // <- TODO: [🏮] Some standard way how to transform errors into warnings and how to handle non-critical fails during the tasks
2760
2813
  /*
2761
2814
  return {
2762
2815
  async listModels() {
@@ -3528,17 +3581,24 @@ function titleToName(value) {
3528
3581
  /**
3529
3582
  * The built-in `fetch' function with a lightweight error handling wrapper as default fetch function used in Promptbook scrapers
3530
3583
  *
3531
- * @private as default `fetch` function used in Promptbook scrapers
3584
+ * @public exported from `@promptbook/core`
3532
3585
  */
3533
- const scraperFetch = async (url, init) => {
3586
+ const promptbookFetch = async (urlOrRequest, init) => {
3534
3587
  try {
3535
- return await fetch(url, init);
3588
+ return await fetch(urlOrRequest, init);
3536
3589
  }
3537
3590
  catch (error) {
3538
3591
  if (!(error instanceof Error)) {
3539
3592
  throw error;
3540
3593
  }
3541
- throw new KnowledgeScrapeError(spaceTrim$1((block) => `
3594
+ let url;
3595
+ if (typeof urlOrRequest === 'string') {
3596
+ url = urlOrRequest;
3597
+ }
3598
+ else if (urlOrRequest instanceof Request) {
3599
+ url = urlOrRequest.url;
3600
+ }
3601
+ throw new PromptbookFetchError(spaceTrim$1((block) => `
3542
3602
  Can not fetch "${url}"
3543
3603
 
3544
3604
  Fetch error:
@@ -3559,7 +3619,7 @@ const scraperFetch = async (url, init) => {
3559
3619
  async function makeKnowledgeSourceHandler(knowledgeSource, tools, options) {
3560
3620
  // console.log('!! makeKnowledgeSourceHandler', knowledgeSource);
3561
3621
  var _a;
3562
- const { fetch = scraperFetch } = tools;
3622
+ const { fetch = promptbookFetch } = tools;
3563
3623
  const { knowledgeSourceContent } = knowledgeSource;
3564
3624
  let { name } = knowledgeSource;
3565
3625
  const { rootDirname = null,
@@ -3700,63 +3760,73 @@ async function prepareKnowledgePieces(knowledgeSources, tools, options) {
3700
3760
  const { maxParallelCount = DEFAULT_MAX_PARALLEL_COUNT, rootDirname, isVerbose = DEFAULT_IS_VERBOSE } = options;
3701
3761
  const knowledgePreparedUnflatten = new Array(knowledgeSources.length);
3702
3762
  await forEachAsync(knowledgeSources, { maxParallelCount }, async (knowledgeSource, index) => {
3703
- let partialPieces = null;
3704
- const sourceHandler = await makeKnowledgeSourceHandler(knowledgeSource, tools, { rootDirname, isVerbose });
3705
- const scrapers = arrayableToArray(tools.scrapers);
3706
- for (const scraper of scrapers) {
3707
- if (!scraper.metadata.mimeTypes.includes(sourceHandler.mimeType)
3708
- // <- TODO: [🦔] Implement mime-type wildcards
3709
- ) {
3710
- continue;
3711
- }
3712
- const partialPiecesUnchecked = await scraper.scrape(sourceHandler);
3713
- if (partialPiecesUnchecked !== null) {
3714
- partialPieces = [...partialPiecesUnchecked];
3715
- // <- TODO: [🪓] Here should be no need for spreading new array, just `partialPieces = partialPiecesUnchecked`
3716
- break;
3717
- }
3718
- console.warn(spaceTrim$1((block) => `
3719
- Cannot scrape knowledge from source despite the scraper \`${scraper.metadata.className}\` supports the mime type "${sourceHandler.mimeType}".
3763
+ try {
3764
+ let partialPieces = null;
3765
+ const sourceHandler = await makeKnowledgeSourceHandler(knowledgeSource, tools, { rootDirname, isVerbose });
3766
+ const scrapers = arrayableToArray(tools.scrapers);
3767
+ for (const scraper of scrapers) {
3768
+ if (!scraper.metadata.mimeTypes.includes(sourceHandler.mimeType)
3769
+ // <- TODO: [🦔] Implement mime-type wildcards
3770
+ ) {
3771
+ continue;
3772
+ }
3773
+ const partialPiecesUnchecked = await scraper.scrape(sourceHandler);
3774
+ if (partialPiecesUnchecked !== null) {
3775
+ partialPieces = [...partialPiecesUnchecked];
3776
+ // <- TODO: [🪓] Here should be no need for spreading new array, just `partialPieces = partialPiecesUnchecked`
3777
+ break;
3778
+ }
3779
+ console.warn(spaceTrim$1((block) => `
3780
+ Cannot scrape knowledge from source despite the scraper \`${scraper.metadata.className}\` supports the mime type "${sourceHandler.mimeType}".
3720
3781
 
3721
- The source:
3722
- ${block(knowledgeSource.knowledgeSourceContent
3723
- .split('\n')
3724
- .map((line) => `> ${line}`)
3725
- .join('\n'))}
3782
+ The source:
3783
+ ${block(knowledgeSource.knowledgeSourceContent
3784
+ .split('\n')
3785
+ .map((line) => `> ${line}`)
3786
+ .join('\n'))}
3726
3787
 
3727
- ${block($registeredScrapersMessage(scrapers))}
3788
+ ${block($registeredScrapersMessage(scrapers))}
3728
3789
 
3729
3790
 
3730
- `));
3731
- }
3732
- if (partialPieces === null) {
3733
- throw new KnowledgeScrapeError(spaceTrim$1((block) => `
3734
- Cannot scrape knowledge
3791
+ `));
3792
+ // <- TODO: [🏮] Some standard way how to transform errors into warnings and how to handle non-critical fails during the tasks
3793
+ }
3794
+ if (partialPieces === null) {
3795
+ throw new KnowledgeScrapeError(spaceTrim$1((block) => `
3796
+ Cannot scrape knowledge
3735
3797
 
3736
- The source:
3737
- > ${block(knowledgeSource.knowledgeSourceContent
3738
- .split('\n')
3739
- .map((line) => `> ${line}`)
3740
- .join('\n'))}
3798
+ The source:
3799
+ > ${block(knowledgeSource.knowledgeSourceContent
3800
+ .split('\n')
3801
+ .map((line) => `> ${line}`)
3802
+ .join('\n'))}
3741
3803
 
3742
- No scraper found for the mime type "${sourceHandler.mimeType}"
3804
+ No scraper found for the mime type "${sourceHandler.mimeType}"
3743
3805
 
3744
- ${block($registeredScrapersMessage(scrapers))}
3806
+ ${block($registeredScrapersMessage(scrapers))}
3745
3807
 
3746
3808
 
3747
- `));
3809
+ `));
3810
+ }
3811
+ const pieces = partialPieces.map((partialPiece) => ({
3812
+ ...partialPiece,
3813
+ sources: [
3814
+ {
3815
+ name: knowledgeSource.name,
3816
+ // line, column <- TODO: [☀]
3817
+ // <- TODO: [❎]
3818
+ },
3819
+ ],
3820
+ }));
3821
+ knowledgePreparedUnflatten[index] = pieces;
3822
+ }
3823
+ catch (error) {
3824
+ if (!(error instanceof Error)) {
3825
+ throw error;
3826
+ }
3827
+ console.warn(error);
3828
+ // <- TODO: [🏮] Some standard way how to transform errors into warnings and how to handle non-critical fails during the tasks
3748
3829
  }
3749
- const pieces = partialPieces.map((partialPiece) => ({
3750
- ...partialPiece,
3751
- sources: [
3752
- {
3753
- name: knowledgeSource.name,
3754
- // line, column <- TODO: [☀]
3755
- // <- TODO: [❎]
3756
- },
3757
- ],
3758
- }));
3759
- knowledgePreparedUnflatten[index] = pieces;
3760
3830
  });
3761
3831
  const knowledgePrepared = knowledgePreparedUnflatten.flat();
3762
3832
  return knowledgePrepared;
@@ -4174,7 +4244,7 @@ function extractParameterNamesFromTask(task) {
4174
4244
  if (parameterNames.has(subparameterName)) {
4175
4245
  parameterNames.delete(subparameterName);
4176
4246
  parameterNames.add(foreach.parameterName);
4177
- // <- TODO: [🚎] Warn/logic error when `subparameterName` not used
4247
+ // <- TODO: [🏮] Warn/logic error when `subparameterName` not used
4178
4248
  }
4179
4249
  }
4180
4250
  }
@@ -5787,6 +5857,7 @@ function createPipelineExecutor(options) {
5787
5857
 
5788
5858
  @see more at https://ptbk.io/prepare-pipeline
5789
5859
  `));
5860
+ // <- TODO: [🏮] Some standard way how to transform errors into warnings and how to handle non-critical fails during the tasks
5790
5861
  }
5791
5862
  let runCount = 0;
5792
5863
  const pipelineExecutorWithCallback = async (inputParameters, onProgress) => {
@@ -6682,11 +6753,12 @@ async function $provideScriptingForNode(options) {
6682
6753
  * @public exported from `@promptbook/remote-server`
6683
6754
  */
6684
6755
  function startRemoteServer(options) {
6685
- const { port, collection, createLlmExecutionTools, isAnonymousModeAllowed, isApplicationModeAllowed, isVerbose = DEFAULT_IS_VERBOSE, } = {
6756
+ const { port, collection, createLlmExecutionTools, isAnonymousModeAllowed, isApplicationModeAllowed, isVerbose = DEFAULT_IS_VERBOSE, login, } = {
6686
6757
  isAnonymousModeAllowed: false,
6687
6758
  isApplicationModeAllowed: false,
6688
6759
  collection: null,
6689
6760
  createLlmExecutionTools: null,
6761
+ login: null,
6690
6762
  ...options,
6691
6763
  };
6692
6764
  // <- TODO: [🦪] Some helper type to be able to use discriminant union types with destructuring
@@ -6753,9 +6825,38 @@ function startRemoteServer(options) {
6753
6825
  response.setHeader('X-Powered-By', 'Promptbook engine');
6754
6826
  next();
6755
6827
  });
6828
+ const swaggerOptions = {
6829
+ definition: {
6830
+ openapi: '3.0.0',
6831
+ info: {
6832
+ title: 'Promptbook Remote Server API',
6833
+ version: '1.0.0',
6834
+ description: 'API documentation for the Promptbook Remote Server',
6835
+ },
6836
+ servers: [
6837
+ {
6838
+ url: `http://localhost:${port}${rootPath}`,
6839
+ // <- TODO: !!!!! Probbably: Pass `remoteServerUrl` instead of `port` and `rootPath`
6840
+ },
6841
+ ],
6842
+ },
6843
+ apis: ['./src/remote-server/**/*.ts'], // Adjust path as needed
6844
+ };
6845
+ const swaggerSpec = swaggerJsdoc(swaggerOptions);
6846
+ app.use([`/api-docs`, `${rootPath}/api-docs`], swaggerUi.serve, swaggerUi.setup(swaggerSpec));
6756
6847
  const runningExecutionTasks = [];
6757
6848
  // <- TODO: [🤬] Identify the users
6758
6849
  // TODO: [🧠] Do here some garbage collection of finished tasks
6850
+ /**
6851
+ * @swagger
6852
+ * /:
6853
+ * get:
6854
+ * summary: Get server details
6855
+ * description: Returns details about the Promptbook server.
6856
+ * responses:
6857
+ * 200:
6858
+ * description: Server details in markdown format.
6859
+ */
6759
6860
  app.get(['/', rootPath], async (request, response) => {
6760
6861
  var _a;
6761
6862
  if ((_a = request.url) === null || _a === void 0 ? void 0 : _a.includes('socket.io')) {
@@ -6792,9 +6893,12 @@ function startRemoteServer(options) {
6792
6893
 
6793
6894
  ## Paths
6794
6895
 
6795
- ${block(app._router.stack
6796
- .map(({ route }) => (route === null || route === void 0 ? void 0 : route.path) || null)
6797
- .filter((path) => path !== null)
6896
+ ${block([
6897
+ ...app._router.stack
6898
+ .map(({ route }) => (route === null || route === void 0 ? void 0 : route.path) || null)
6899
+ .filter((path) => path !== null),
6900
+ '/api-docs',
6901
+ ]
6798
6902
  .map((path) => `- ${path}`)
6799
6903
  .join('\n'))}
6800
6904
 
@@ -6812,7 +6916,96 @@ function startRemoteServer(options) {
6812
6916
  https://github.com/webgptorg/promptbook
6813
6917
  `));
6814
6918
  });
6815
- app.get(`${rootPath}/books`, async (request, response) => {
6919
+ /**
6920
+ * @swagger
6921
+ *
6922
+ * /login:
6923
+ * post:
6924
+ * summary: Login to the server
6925
+ * description: Login to the server and get identification.
6926
+ * requestBody:
6927
+ * required: true
6928
+ * content:
6929
+ * application/json:
6930
+ * schema:
6931
+ * type: object
6932
+ * properties:
6933
+ * username:
6934
+ * type: string
6935
+ * password:
6936
+ * type: string
6937
+ * appId:
6938
+ * type: string
6939
+ * responses:
6940
+ * 200:
6941
+ * description: Successful login
6942
+ * content:
6943
+ * application/json:
6944
+ * schema:
6945
+ * type: object
6946
+ * properties:
6947
+ * identification:
6948
+ * type: object
6949
+ */
6950
+ app.post([`/login`, `${rootPath}/login`], async (request, response) => {
6951
+ if (!isApplicationModeAllowed || login === null) {
6952
+ response.status(400).send('Application mode is not allowed');
6953
+ return;
6954
+ }
6955
+ try {
6956
+ const username = request.body.username;
6957
+ const password = request.body.password;
6958
+ const appId = request.body.appId;
6959
+ const { isSuccess, error, message, identification } = await login({
6960
+ username,
6961
+ password,
6962
+ appId,
6963
+ rawRequest: request,
6964
+ rawResponse: response,
6965
+ });
6966
+ response.status(201).send({
6967
+ isSuccess,
6968
+ message,
6969
+ error: error ? serializeError(error) : undefined,
6970
+ identification,
6971
+ });
6972
+ return;
6973
+ }
6974
+ catch (error) {
6975
+ if (!(error instanceof Error)) {
6976
+ throw error;
6977
+ }
6978
+ if (error instanceof AuthenticationError) {
6979
+ response.status(401).send({
6980
+ isSuccess: false,
6981
+ message: error.message,
6982
+ error: serializeError(error),
6983
+ });
6984
+ }
6985
+ console.warn(`Login function thrown different error than AuthenticationError`, {
6986
+ error,
6987
+ serializedError: serializeError(error),
6988
+ });
6989
+ response.status(400).send({ error: serializeError(error) });
6990
+ }
6991
+ });
6992
+ /**
6993
+ * @swagger
6994
+ * /books:
6995
+ * get:
6996
+ * summary: List all books
6997
+ * description: Returns a list of all available books in the collection.
6998
+ * responses:
6999
+ * 200:
7000
+ * description: A list of books.
7001
+ * content:
7002
+ * application/json:
7003
+ * schema:
7004
+ * type: array
7005
+ * items:
7006
+ * type: string
7007
+ */
7008
+ app.get([`/books`, `${rootPath}/books`], async (request, response) => {
6816
7009
  if (collection === null) {
6817
7010
  response.status(500).send('No collection available');
6818
7011
  return;
@@ -6822,7 +7015,30 @@ function startRemoteServer(options) {
6822
7015
  response.send(pipelines);
6823
7016
  });
6824
7017
  // TODO: [🧠] Is it secure / good idea to expose source codes of hosted books
6825
- app.get(`${rootPath}/books/*`, async (request, response) => {
7018
+ /**
7019
+ * @swagger
7020
+ * /books/{bookId}:
7021
+ * get:
7022
+ * summary: Get book content
7023
+ * description: Returns the content of a specific book.
7024
+ * parameters:
7025
+ * - in: path
7026
+ * name: bookId
7027
+ * required: true
7028
+ * schema:
7029
+ * type: string
7030
+ * description: The ID of the book to retrieve.
7031
+ * responses:
7032
+ * 200:
7033
+ * description: The content of the book.
7034
+ * content:
7035
+ * text/markdown:
7036
+ * schema:
7037
+ * type: string
7038
+ * 404:
7039
+ * description: Book not found.
7040
+ */
7041
+ app.get([`/books/*`, `${rootPath}/books/*`], async (request, response) => {
6826
7042
  try {
6827
7043
  if (collection === null) {
6828
7044
  response.status(500).send('No collection nor books available');
@@ -6876,10 +7092,26 @@ function startRemoteServer(options) {
6876
7092
  };
6877
7093
  }
6878
7094
  }
6879
- app.get(`${rootPath}/executions`, async (request, response) => {
7095
+ /**
7096
+ * @swagger
7097
+ * /executions:
7098
+ * get:
7099
+ * summary: List all executions
7100
+ * description: Returns a list of all running execution tasks.
7101
+ * responses:
7102
+ * 200:
7103
+ * description: A list of execution tasks.
7104
+ * content:
7105
+ * application/json:
7106
+ * schema:
7107
+ * type: array
7108
+ * items:
7109
+ * type: object
7110
+ */
7111
+ app.get([`/executions`, `${rootPath}/executions`], async (request, response) => {
6880
7112
  response.send(runningExecutionTasks.map((runningExecutionTask) => exportExecutionTask(runningExecutionTask, false)));
6881
7113
  });
6882
- app.get(`${rootPath}/executions/last`, async (request, response) => {
7114
+ app.get([`/executions/last`, `${rootPath}/executions/last`], async (request, response) => {
6883
7115
  // TODO: [🤬] Filter only for user
6884
7116
  if (runningExecutionTasks.length === 0) {
6885
7117
  response.status(404).send('No execution tasks found');
@@ -6888,7 +7120,7 @@ function startRemoteServer(options) {
6888
7120
  const lastExecutionTask = runningExecutionTasks[runningExecutionTasks.length - 1];
6889
7121
  response.send(exportExecutionTask(lastExecutionTask, true));
6890
7122
  });
6891
- app.get(`${rootPath}/executions/:taskId`, async (request, response) => {
7123
+ app.get([`/executions/:taskId`, `${rootPath}/executions/:taskId`], async (request, response) => {
6892
7124
  const { taskId } = request.params;
6893
7125
  // TODO: [🤬] Filter only for user
6894
7126
  const executionTask = runningExecutionTasks.find((executionTask) => executionTask.taskId === taskId);
@@ -6900,7 +7132,36 @@ function startRemoteServer(options) {
6900
7132
  }
6901
7133
  response.send(exportExecutionTask(executionTask, true));
6902
7134
  });
6903
- app.post(`${rootPath}/executions/new`, async (request, response) => {
7135
+ /**
7136
+ * @swagger
7137
+ * /executions/new:
7138
+ * post:
7139
+ * summary: Start a new execution
7140
+ * description: Starts a new execution task for a given pipeline.
7141
+ * requestBody:
7142
+ * required: true
7143
+ * content:
7144
+ * application/json:
7145
+ * schema:
7146
+ * type: object
7147
+ * properties:
7148
+ * pipelineUrl:
7149
+ * type: string
7150
+ * inputParameters:
7151
+ * type: object
7152
+ * identification:
7153
+ * type: object
7154
+ * responses:
7155
+ * 200:
7156
+ * description: The newly created execution task.
7157
+ * content:
7158
+ * application/json:
7159
+ * schema:
7160
+ * type: object
7161
+ * 400:
7162
+ * description: Invalid input.
7163
+ */
7164
+ app.post([`/executions/new`, `${rootPath}/executions/new`], async (request, response) => {
6904
7165
  try {
6905
7166
  const { inputParameters, identification /* <- [🤬] */ } = request.body;
6906
7167
  const pipelineUrl = request.body.pipelineUrl || request.body.book;
@@ -7077,6 +7338,15 @@ function startRemoteServer(options) {
7077
7338
  }
7078
7339
  let isDestroyed = false;
7079
7340
  return {
7341
+ get httpServer() {
7342
+ return httpServer;
7343
+ },
7344
+ get expressApp() {
7345
+ return app;
7346
+ },
7347
+ get socketIoServer() {
7348
+ return server;
7349
+ },
7080
7350
  get isDestroyed() {
7081
7351
  return isDestroyed;
7082
7352
  },