@promptbook/remote-server 0.89.0-2 → 0.89.0-20

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 (48) hide show
  1. package/README.md +10 -6
  2. package/esm/index.es.js +518 -242
  3. package/esm/index.es.js.map +1 -1
  4. package/esm/typings/servers.d.ts +40 -0
  5. package/esm/typings/src/_packages/core.index.d.ts +20 -8
  6. package/esm/typings/src/_packages/remote-client.index.d.ts +6 -8
  7. package/esm/typings/src/_packages/remote-server.index.d.ts +6 -6
  8. package/esm/typings/src/_packages/types.index.d.ts +18 -16
  9. package/esm/typings/src/cli/cli-commands/login.d.ts +0 -1
  10. package/esm/typings/src/cli/common/$addGlobalOptionsToCommand.d.ts +7 -0
  11. package/esm/typings/src/cli/common/$provideLlmToolsForCli.d.ts +28 -0
  12. package/esm/typings/src/cli/test/ptbk.d.ts +1 -1
  13. package/esm/typings/src/commands/EXPECT/expectCommandParser.d.ts +2 -0
  14. package/esm/typings/src/config.d.ts +24 -26
  15. package/esm/typings/src/errors/0-index.d.ts +9 -0
  16. package/esm/typings/src/errors/AuthenticationError.d.ts +9 -0
  17. package/esm/typings/src/errors/PipelineExecutionError.d.ts +1 -1
  18. package/esm/typings/src/errors/PromptbookFetchError.d.ts +9 -0
  19. package/esm/typings/src/errors/WrappedError.d.ts +10 -0
  20. package/esm/typings/src/errors/assertsError.d.ts +11 -0
  21. package/esm/typings/src/execution/PromptbookFetch.d.ts +1 -1
  22. package/esm/typings/src/llm-providers/_common/register/$provideEnvFilename.d.ts +12 -0
  23. package/esm/typings/src/llm-providers/_common/register/$provideLlmToolsConfigurationFromEnv.d.ts +2 -8
  24. package/esm/typings/src/llm-providers/_common/register/$provideLlmToolsForTestingAndScriptsAndPlayground.d.ts +2 -0
  25. package/esm/typings/src/llm-providers/_common/register/$provideLlmToolsForWizzardOrCli.d.ts +45 -1
  26. package/esm/typings/src/llm-providers/_common/register/$provideLlmToolsFromEnv.d.ts +1 -0
  27. package/esm/typings/src/llm-providers/anthropic-claude/AnthropicClaudeExecutionToolsOptions.d.ts +1 -1
  28. package/esm/typings/src/llm-providers/anthropic-claude/register-configuration.d.ts +1 -1
  29. package/esm/typings/src/remote-server/RemoteServer.d.ts +23 -0
  30. package/esm/typings/src/remote-server/socket-types/_subtypes/{PromptbookServer_Identification.d.ts → Identification.d.ts} +3 -3
  31. package/esm/typings/src/remote-server/socket-types/_subtypes/identificationToPromptbookToken.d.ts +11 -0
  32. package/esm/typings/src/remote-server/socket-types/_subtypes/promptbookTokenToIdentification.d.ts +10 -0
  33. package/esm/typings/src/remote-server/socket-types/listModels/PromptbookServer_ListModels_Request.d.ts +2 -2
  34. package/esm/typings/src/remote-server/socket-types/prepare/PromptbookServer_PreparePipeline_Request.d.ts +2 -2
  35. package/esm/typings/src/remote-server/socket-types/prompt/PromptbookServer_Prompt_Request.d.ts +2 -2
  36. package/esm/typings/src/remote-server/startRemoteServer.d.ts +2 -3
  37. package/esm/typings/src/remote-server/types/RemoteClientOptions.d.ts +4 -12
  38. package/esm/typings/src/remote-server/types/RemoteServerOptions.d.ts +89 -4
  39. package/esm/typings/src/scrapers/_common/utils/{scraperFetch.d.ts → promptbookFetch.d.ts} +2 -2
  40. package/esm/typings/src/storage/env-storage/$EnvStorage.d.ts +40 -0
  41. package/esm/typings/src/types/typeAliases.d.ts +19 -0
  42. package/esm/typings/src/utils/organization/TODO_narrow.d.ts +6 -0
  43. package/package.json +11 -5
  44. package/umd/index.umd.js +422 -146
  45. package/umd/index.umd.js.map +1 -1
  46. package/esm/typings/src/cli/test/ptbk2.d.ts +0 -5
  47. package/esm/typings/src/playground/BrjappConnector.d.ts +0 -67
  48. package/esm/typings/src/playground/brjapp-api-schema.d.ts +0 -12879
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('express'), require('http'), require('socket.io'), require('spacetrim'), require('waitasecond'), require('crypto'), require('child_process'), require('fs/promises'), require('path'), require('rxjs'), require('prettier'), require('prettier/parser-html'), require('crypto-js/enc-hex'), require('crypto-js/sha256'), require('crypto-js'), require('mime-types'), require('papaparse')) :
3
- typeof define === 'function' && define.amd ? define(['exports', 'colors', 'express', 'http', 'socket.io', 'spacetrim', 'waitasecond', 'crypto', 'child_process', 'fs/promises', 'path', 'rxjs', 'prettier', 'prettier/parser-html', 'crypto-js/enc-hex', 'crypto-js/sha256', 'crypto-js', 'mime-types', 'papaparse'], factory) :
4
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global["promptbook-remote-server"] = {}, global.colors, global.express, global.http, global.socket_io, global.spaceTrim, global.waitasecond, global.crypto, global.child_process, global.promises, global.path, global.rxjs, global.prettier, global.parserHtml, global.hexEncoder, global.sha256, global.cryptoJs, global.mimeTypes, global.papaparse));
5
- })(this, (function (exports, colors, express, http, socket_io, spaceTrim, waitasecond, crypto, child_process, promises, path, rxjs, prettier, parserHtml, hexEncoder, sha256, cryptoJs, mimeTypes, papaparse) { 'use strict';
2
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('colors'), require('express'), require('http'), require('socket.io'), require('spacetrim'), require('swagger-jsdoc'), require('swagger-ui-express'), require('waitasecond'), require('crypto'), require('child_process'), require('fs/promises'), require('path'), require('rxjs'), require('prettier'), require('prettier/parser-html'), require('crypto-js/enc-hex'), require('crypto-js/sha256'), require('crypto-js'), require('mime-types'), require('papaparse')) :
3
+ typeof define === 'function' && define.amd ? define(['exports', 'colors', 'express', 'http', 'socket.io', 'spacetrim', 'swagger-jsdoc', 'swagger-ui-express', 'waitasecond', 'crypto', 'child_process', 'fs/promises', 'path', 'rxjs', 'prettier', 'prettier/parser-html', 'crypto-js/enc-hex', 'crypto-js/sha256', 'crypto-js', 'mime-types', 'papaparse'], factory) :
4
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global["promptbook-remote-server"] = {}, global.colors, global.express, global.http, global.socket_io, global.spaceTrim, global.swaggerJsdoc, global.swaggerUi, global.waitasecond, global.crypto, global.child_process, global.promises, global.path, global.rxjs, global.prettier, global.parserHtml, global.hexEncoder, global.sha256, global.cryptoJs, global.mimeTypes, global.papaparse));
5
+ })(this, (function (exports, colors, express, http, socket_io, spaceTrim, swaggerJsdoc, swaggerUi, waitasecond, crypto, child_process, promises, path, rxjs, prettier, parserHtml, hexEncoder, sha256, cryptoJs, mimeTypes, papaparse) { 'use strict';
6
6
 
7
7
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
8
8
 
@@ -10,6 +10,8 @@
10
10
  var express__default = /*#__PURE__*/_interopDefaultLegacy(express);
11
11
  var http__default = /*#__PURE__*/_interopDefaultLegacy(http);
12
12
  var spaceTrim__default = /*#__PURE__*/_interopDefaultLegacy(spaceTrim);
13
+ var swaggerJsdoc__default = /*#__PURE__*/_interopDefaultLegacy(swaggerJsdoc);
14
+ var swaggerUi__default = /*#__PURE__*/_interopDefaultLegacy(swaggerUi);
13
15
  var parserHtml__default = /*#__PURE__*/_interopDefaultLegacy(parserHtml);
14
16
  var hexEncoder__default = /*#__PURE__*/_interopDefaultLegacy(hexEncoder);
15
17
  var sha256__default = /*#__PURE__*/_interopDefaultLegacy(sha256);
@@ -28,7 +30,7 @@
28
30
  * @generated
29
31
  * @see https://github.com/webgptorg/promptbook
30
32
  */
31
- const PROMPTBOOK_ENGINE_VERSION = '0.89.0-2';
33
+ const PROMPTBOOK_ENGINE_VERSION = '0.89.0-20';
32
34
  /**
33
35
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
34
36
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -82,6 +84,7 @@
82
84
  * @public exported from `@promptbook/core`
83
85
  */
84
86
  const CLAIM = `It's time for a paradigm shift. The future of software in plain English, French or Latin`;
87
+ // <- TODO: [🐊] Pick the best claim
85
88
  /**
86
89
  * When the title is not provided, the default title is used
87
90
  *
@@ -114,6 +117,7 @@
114
117
  infinity: '(infinity; ∞)',
115
118
  negativeInfinity: '(negative infinity; -∞)',
116
119
  unserializable: '(unserializable value)',
120
+ circular: '(circular JSON)',
117
121
  };
118
122
  /**
119
123
  * Small number limit
@@ -153,6 +157,7 @@
153
157
  */
154
158
  const DEFAULT_MAX_EXECUTION_ATTEMPTS = 10; // <- TODO: [🤹‍♂️]
155
159
  // <- TODO: [🕝] Make also `BOOKS_DIRNAME_ALTERNATIVES`
160
+ // TODO: Just `.promptbook` in config, hardcode subfolders like `download-cache` or `execution-cache`
156
161
  /**
157
162
  * Where to store the temporary downloads
158
163
  *
@@ -204,9 +209,138 @@
204
209
  true);
205
210
  /**
206
211
  * Note: [💞] Ignore a discrepancy between file name and entity name
207
- * TODO: [🧠][🧜‍♂️] Maybe join remoteUrl and path into single value
212
+ * TODO: [🧠][🧜‍♂️] Maybe join remoteServerUrl and path into single value
208
213
  */
209
214
 
215
+ /**
216
+ * Make error report URL for the given error
217
+ *
218
+ * @private private within the repository
219
+ */
220
+ function getErrorReportUrl(error) {
221
+ const report = {
222
+ title: `🐜 Error report from ${NAME}`,
223
+ body: spaceTrim__default["default"]((block) => `
224
+
225
+
226
+ \`${error.name || 'Error'}\` has occurred in the [${NAME}], please look into it @${ADMIN_GITHUB_NAME}.
227
+
228
+ \`\`\`
229
+ ${block(error.message || '(no error message)')}
230
+ \`\`\`
231
+
232
+
233
+ ## More info:
234
+
235
+ - **Promptbook engine version:** ${PROMPTBOOK_ENGINE_VERSION}
236
+ - **Book language version:** ${BOOK_LANGUAGE_VERSION}
237
+ - **Time:** ${new Date().toISOString()}
238
+
239
+ <details>
240
+ <summary>Stack trace:</summary>
241
+
242
+ ## Stack trace:
243
+
244
+ \`\`\`stacktrace
245
+ ${block(error.stack || '(empty)')}
246
+ \`\`\`
247
+ </details>
248
+
249
+ `),
250
+ };
251
+ const reportUrl = new URL(`https://github.com/webgptorg/promptbook/issues/new`);
252
+ reportUrl.searchParams.set('labels', 'bug');
253
+ reportUrl.searchParams.set('assignees', ADMIN_GITHUB_NAME);
254
+ reportUrl.searchParams.set('title', report.title);
255
+ reportUrl.searchParams.set('body', report.body);
256
+ return reportUrl;
257
+ }
258
+
259
+ /**
260
+ * This error type indicates that the error should not happen and its last check before crashing with some other error
261
+ *
262
+ * @public exported from `@promptbook/core`
263
+ */
264
+ class UnexpectedError extends Error {
265
+ constructor(message) {
266
+ super(spaceTrim.spaceTrim((block) => `
267
+ ${block(message)}
268
+
269
+ Note: This error should not happen.
270
+ It's probbably a bug in the pipeline collection
271
+
272
+ Please report issue:
273
+ ${block(getErrorReportUrl(new Error(message)).href)}
274
+
275
+ Or contact us on ${ADMIN_EMAIL}
276
+
277
+ `));
278
+ this.name = 'UnexpectedError';
279
+ Object.setPrototypeOf(this, UnexpectedError.prototype);
280
+ }
281
+ }
282
+
283
+ /**
284
+ * This error type indicates that somewhere in the code non-Error object was thrown and it was wrapped into the `WrappedError`
285
+ *
286
+ * @public exported from `@promptbook/core`
287
+ */
288
+ class WrappedError extends Error {
289
+ constructor(whatWasThrown) {
290
+ const tag = `[🤮]`;
291
+ console.error(tag, whatWasThrown);
292
+ super(spaceTrim.spaceTrim(`
293
+ Non-Error object was thrown
294
+
295
+ Note: Look for ${tag} in the console for more details
296
+ Please report issue on ${ADMIN_EMAIL}
297
+ `));
298
+ this.name = 'WrappedError';
299
+ Object.setPrototypeOf(this, WrappedError.prototype);
300
+ }
301
+ }
302
+
303
+ /**
304
+ * Helper used in catch blocks to assert that the error is an instance of `Error`
305
+ *
306
+ * @param whatWasThrown Any object that was thrown
307
+ * @returns Nothing if the error is an instance of `Error`
308
+ * @throws `WrappedError` or `UnexpectedError` if the error is not standard
309
+ *
310
+ * @private within the repository
311
+ */
312
+ function assertsError(whatWasThrown) {
313
+ // Case 1: Handle error which was rethrown as `WrappedError`
314
+ if (whatWasThrown instanceof WrappedError) {
315
+ const wrappedError = whatWasThrown;
316
+ throw wrappedError;
317
+ }
318
+ // Case 2: Handle unexpected errors
319
+ if (whatWasThrown instanceof UnexpectedError) {
320
+ const unexpectedError = whatWasThrown;
321
+ throw unexpectedError;
322
+ }
323
+ // Case 3: Handle standard errors - keep them up to consumer
324
+ if (whatWasThrown instanceof Error) {
325
+ return;
326
+ }
327
+ // Case 4: Handle non-standard errors - wrap them into `WrappedError` and throw
328
+ throw new WrappedError(whatWasThrown);
329
+ }
330
+
331
+ /**
332
+ * AuthenticationError is thrown from login function which is dependency of remote server
333
+ *
334
+ * @public exported from `@promptbook/core`
335
+ */
336
+ class AuthenticationError extends Error {
337
+ constructor(message) {
338
+ super(message);
339
+ this.name = 'AuthenticationError';
340
+ Object.setPrototypeOf(this, AuthenticationError.prototype);
341
+ }
342
+ }
343
+
210
344
  /**
211
345
  * Generates random token
212
346
  *
@@ -238,7 +372,7 @@
238
372
  }
239
373
  }
240
374
  /**
241
- * TODO: !!!!!! Add id to all errors
375
+ * TODO: [🧠][🌂] Add id to all errors
242
376
  */
243
377
 
244
378
  /**
@@ -436,70 +570,15 @@
436
570
  }
437
571
 
438
572
  /**
439
- * Make error report URL for the given error
440
- *
441
- * @private private within the repository
442
- */
443
- function getErrorReportUrl(error) {
444
- const report = {
445
- title: `🐜 Error report from ${NAME}`,
446
- body: spaceTrim__default["default"]((block) => `
447
-
448
-
449
- \`${error.name || 'Error'}\` has occurred in the [${NAME}], please look into it @${ADMIN_GITHUB_NAME}.
450
-
451
- \`\`\`
452
- ${block(error.message || '(no error message)')}
453
- \`\`\`
454
-
455
-
456
- ## More info:
457
-
458
- - **Promptbook engine version:** ${PROMPTBOOK_ENGINE_VERSION}
459
- - **Book language version:** ${BOOK_LANGUAGE_VERSION}
460
- - **Time:** ${new Date().toISOString()}
461
-
462
- <details>
463
- <summary>Stack trace:</summary>
464
-
465
- ## Stack trace:
466
-
467
- \`\`\`stacktrace
468
- ${block(error.stack || '(empty)')}
469
- \`\`\`
470
- </details>
471
-
472
- `),
473
- };
474
- const reportUrl = new URL(`https://github.com/webgptorg/promptbook/issues/new`);
475
- reportUrl.searchParams.set('labels', 'bug');
476
- reportUrl.searchParams.set('assignees', ADMIN_GITHUB_NAME);
477
- reportUrl.searchParams.set('title', report.title);
478
- reportUrl.searchParams.set('body', report.body);
479
- return reportUrl;
480
- }
481
-
482
- /**
483
- * This error type indicates that the error should not happen and its last check before crashing with some other error
573
+ * Error thrown when a fetch request fails
484
574
  *
485
575
  * @public exported from `@promptbook/core`
486
576
  */
487
- class UnexpectedError extends Error {
577
+ class PromptbookFetchError extends Error {
488
578
  constructor(message) {
489
- super(spaceTrim.spaceTrim((block) => `
490
- ${block(message)}
491
-
492
- Note: This error should not happen.
493
- It's probbably a bug in the pipeline collection
494
-
495
- Please report issue:
496
- ${block(getErrorReportUrl(new Error(message)).href)}
497
-
498
- Or contact us on ${ADMIN_EMAIL}
499
-
500
- `));
501
- this.name = 'UnexpectedError';
502
- Object.setPrototypeOf(this, UnexpectedError.prototype);
579
+ super(message);
580
+ this.name = 'PromptbookFetchError';
581
+ Object.setPrototypeOf(this, PromptbookFetchError.prototype);
503
582
  }
504
583
  }
505
584
 
@@ -523,7 +602,10 @@
523
602
  PipelineExecutionError,
524
603
  PipelineLogicError,
525
604
  PipelineUrlError,
605
+ AuthenticationError,
606
+ PromptbookFetchError,
526
607
  UnexpectedError,
608
+ WrappedError,
527
609
  // TODO: [🪑]> VersionMismatchError,
528
610
  };
529
611
  /**
@@ -575,6 +657,10 @@
575
657
 
576
658
  Cannot serialize error with name "${name}"
577
659
 
660
+ Authors of Promptbook probably forgot to add this error into the list of errors:
661
+ https://github.com/webgptorg/promptbook/blob/main/src/errors/0-index.ts
662
+
663
+
578
664
  ${block(stack || message)}
579
665
 
580
666
  `));
@@ -778,9 +864,7 @@
778
864
  return result.trim();
779
865
  }
780
866
  catch (error) {
781
- if (!(error instanceof Error)) {
782
- throw error;
783
- }
867
+ assertsError(error);
784
868
  return null;
785
869
  }
786
870
  }
@@ -858,9 +942,7 @@
858
942
  return result.trim() + toExec;
859
943
  }
860
944
  catch (error) {
861
- if (!(error instanceof Error)) {
862
- throw error;
863
- }
945
+ assertsError(error);
864
946
  return null;
865
947
  }
866
948
  }
@@ -891,9 +973,7 @@
891
973
  throw new Error(`Can not locate app ${appName} on Windows.`);
892
974
  }
893
975
  catch (error) {
894
- if (!(error instanceof Error)) {
895
- throw error;
896
- }
976
+ assertsError(error);
897
977
  return null;
898
978
  }
899
979
  }
@@ -1131,9 +1211,7 @@
1131
1211
  JSON.stringify(value); // <- TODO: [0]
1132
1212
  }
1133
1213
  catch (error) {
1134
- if (!(error instanceof Error)) {
1135
- throw error;
1136
- }
1214
+ assertsError(error);
1137
1215
  throw new UnexpectedError(spaceTrim__default["default"]((block) => `
1138
1216
  \`${name}\` is not serializable
1139
1217
 
@@ -1741,9 +1819,7 @@
1741
1819
  return true;
1742
1820
  }
1743
1821
  catch (error) {
1744
- if (!(error instanceof Error)) {
1745
- throw error;
1746
- }
1822
+ assertsError(error);
1747
1823
  if (error.message.includes('Unexpected token')) {
1748
1824
  return false;
1749
1825
  }
@@ -1881,8 +1957,8 @@
1881
1957
  updatedAt = new Date();
1882
1958
  errors.push(...executionResult.errors);
1883
1959
  warnings.push(...executionResult.warnings);
1884
- // <- TODO: !!! Only unique errors and warnings should be added (or filtered)
1885
- // TODO: [🧠] !!! errors, warning, isSuccessful are redundant both in `ExecutionTask` and `ExecutionTask.currentValue`
1960
+ // <- TODO: [🌂] Only unique errors and warnings should be added (or filtered)
1961
+ // TODO: [🧠] !! errors, warning, isSuccessful are redundant both in `ExecutionTask` and `ExecutionTask.currentValue`
1886
1962
  // Also maybe move `ExecutionTask.currentValue.usage` -> `ExecutionTask.usage`
1887
1963
  // And delete `ExecutionTask.currentValue.preparedPipeline`
1888
1964
  assertsTaskSuccessful(executionResult);
@@ -1892,6 +1968,7 @@
1892
1968
  partialResultSubject.next(executionResult);
1893
1969
  }
1894
1970
  catch (error) {
1971
+ assertsError(error);
1895
1972
  status = 'ERROR';
1896
1973
  errors.push(error);
1897
1974
  partialResultSubject.error(error);
@@ -2702,14 +2779,15 @@
2702
2779
  }
2703
2780
  }
2704
2781
  catch (error) {
2705
- if (!(error instanceof Error) || error instanceof UnexpectedError) {
2782
+ assertsError(error);
2783
+ if (error instanceof UnexpectedError) {
2706
2784
  throw error;
2707
2785
  }
2708
2786
  errors.push({ llmExecutionTools, error });
2709
2787
  }
2710
2788
  }
2711
2789
  if (errors.length === 1) {
2712
- throw errors[0];
2790
+ throw errors[0].error;
2713
2791
  }
2714
2792
  else if (errors.length > 1) {
2715
2793
  throw new PipelineExecutionError(
@@ -3543,17 +3621,22 @@
3543
3621
  /**
3544
3622
  * The built-in `fetch' function with a lightweight error handling wrapper as default fetch function used in Promptbook scrapers
3545
3623
  *
3546
- * @private as default `fetch` function used in Promptbook scrapers
3624
+ * @public exported from `@promptbook/core`
3547
3625
  */
3548
- const scraperFetch = async (url, init) => {
3626
+ const promptbookFetch = async (urlOrRequest, init) => {
3549
3627
  try {
3550
- return await fetch(url, init);
3628
+ return await fetch(urlOrRequest, init);
3551
3629
  }
3552
3630
  catch (error) {
3553
- if (!(error instanceof Error)) {
3554
- throw error;
3631
+ assertsError(error);
3632
+ let url;
3633
+ if (typeof urlOrRequest === 'string') {
3634
+ url = urlOrRequest;
3555
3635
  }
3556
- throw new KnowledgeScrapeError(spaceTrim__default["default"]((block) => `
3636
+ else if (urlOrRequest instanceof Request) {
3637
+ url = urlOrRequest.url;
3638
+ }
3639
+ throw new PromptbookFetchError(spaceTrim__default["default"]((block) => `
3557
3640
  Can not fetch "${url}"
3558
3641
 
3559
3642
  Fetch error:
@@ -3574,7 +3657,7 @@
3574
3657
  async function makeKnowledgeSourceHandler(knowledgeSource, tools, options) {
3575
3658
  // console.log('!! makeKnowledgeSourceHandler', knowledgeSource);
3576
3659
  var _a;
3577
- const { fetch = scraperFetch } = tools;
3660
+ const { fetch = promptbookFetch } = tools;
3578
3661
  const { knowledgeSourceContent } = knowledgeSource;
3579
3662
  let { name } = knowledgeSource;
3580
3663
  const { rootDirname = null,
@@ -3776,9 +3859,7 @@
3776
3859
  knowledgePreparedUnflatten[index] = pieces;
3777
3860
  }
3778
3861
  catch (error) {
3779
- if (!(error instanceof Error)) {
3780
- throw error;
3781
- }
3862
+ assertsError(error);
3782
3863
  console.warn(error);
3783
3864
  // <- TODO: [🏮] Some standard way how to transform errors into warnings and how to handle non-critical fails during the tasks
3784
3865
  }
@@ -4070,13 +4151,19 @@
4070
4151
  return value.toISOString();
4071
4152
  }
4072
4153
  else {
4073
- return JSON.stringify(value);
4154
+ try {
4155
+ return JSON.stringify(value);
4156
+ }
4157
+ catch (error) {
4158
+ if (error instanceof TypeError && error.message.includes('circular structure')) {
4159
+ return VALUE_STRINGS.circular;
4160
+ }
4161
+ throw error;
4162
+ }
4074
4163
  }
4075
4164
  }
4076
4165
  catch (error) {
4077
- if (!(error instanceof Error)) {
4078
- throw error;
4079
- }
4166
+ assertsError(error);
4080
4167
  console.error(error);
4081
4168
  return VALUE_STRINGS.unserializable;
4082
4169
  }
@@ -4133,9 +4220,7 @@
4133
4220
  }
4134
4221
  }
4135
4222
  catch (error) {
4136
- if (!(error instanceof Error)) {
4137
- throw error;
4138
- }
4223
+ assertsError(error);
4139
4224
  throw new ParseError(spaceTrim.spaceTrim((block) => `
4140
4225
  Can not extract variables from the script
4141
4226
  ${block(error.stack || error.message)}
@@ -5017,9 +5102,7 @@
5017
5102
  break scripts;
5018
5103
  }
5019
5104
  catch (error) {
5020
- if (!(error instanceof Error)) {
5021
- throw error;
5022
- }
5105
+ assertsError(error);
5023
5106
  if (error instanceof UnexpectedError) {
5024
5107
  throw error;
5025
5108
  }
@@ -5089,9 +5172,7 @@
5089
5172
  break scripts;
5090
5173
  }
5091
5174
  catch (error) {
5092
- if (!(error instanceof Error)) {
5093
- throw error;
5094
- }
5175
+ assertsError(error);
5095
5176
  if (error instanceof UnexpectedError) {
5096
5177
  throw error;
5097
5178
  }
@@ -5712,9 +5793,7 @@
5712
5793
  await Promise.all(resolving);
5713
5794
  }
5714
5795
  catch (error /* <- Note: [3] */) {
5715
- if (!(error instanceof Error)) {
5716
- throw error;
5717
- }
5796
+ assertsError(error);
5718
5797
  // Note: No need to rethrow UnexpectedError
5719
5798
  // if (error instanceof UnexpectedError) {
5720
5799
  // Note: Count usage, [🧠] Maybe put to separate function executionReportJsonToUsage + DRY [🤹‍♂️]
@@ -6616,9 +6695,7 @@
6616
6695
  }
6617
6696
  }
6618
6697
  catch (error) {
6619
- if (!(error instanceof Error)) {
6620
- throw error;
6621
- }
6698
+ assertsError(error);
6622
6699
  if (error instanceof ReferenceError) {
6623
6700
  const undefinedName = error.message.split(' ')[0];
6624
6701
  /*
@@ -6708,11 +6785,12 @@
6708
6785
  * @public exported from `@promptbook/remote-server`
6709
6786
  */
6710
6787
  function startRemoteServer(options) {
6711
- const { port, collection, createLlmExecutionTools, isAnonymousModeAllowed, isApplicationModeAllowed, isVerbose = DEFAULT_IS_VERBOSE, } = {
6788
+ const { port, collection, createLlmExecutionTools, createExecutionTools, isAnonymousModeAllowed, isApplicationModeAllowed, isVerbose = DEFAULT_IS_VERBOSE, login, } = {
6712
6789
  isAnonymousModeAllowed: false,
6713
6790
  isApplicationModeAllowed: false,
6714
6791
  collection: null,
6715
6792
  createLlmExecutionTools: null,
6793
+ login: null,
6716
6794
  ...options,
6717
6795
  };
6718
6796
  // <- TODO: [🦪] Some helper type to be able to use discriminant union types with destructuring
@@ -6755,6 +6833,7 @@
6755
6833
  // Note: Application mode
6756
6834
  const { appId, userId, customOptions } = identification;
6757
6835
  llm = await createLlmExecutionTools({
6836
+ isAnonymous: false,
6758
6837
  appId,
6759
6838
  userId,
6760
6839
  customOptions,
@@ -6763,13 +6842,20 @@
6763
6842
  else {
6764
6843
  throw new PipelineExecutionError(`You must provide either llmToolsConfiguration or non-anonymous mode must be propperly configured`);
6765
6844
  }
6766
- const fs = $provideFilesystemForNode();
6767
- const executables = await $provideExecutablesForNode();
6845
+ const customExecutionTools = createExecutionTools ? await createExecutionTools(identification) : {};
6846
+ const fs = customExecutionTools.fs || $provideFilesystemForNode();
6847
+ const executables = customExecutionTools.executables || (await $provideExecutablesForNode());
6848
+ const scrapers = customExecutionTools.scrapers || (await $provideScrapersForNode({ fs, llm, executables }));
6849
+ const script = customExecutionTools.script || (await $provideScriptingForNode({}));
6850
+ const fetch = customExecutionTools.fetch || promptbookFetch;
6851
+ const userInterface = customExecutionTools.userInterface || undefined;
6768
6852
  const tools = {
6769
6853
  llm,
6770
6854
  fs,
6771
- scrapers: await $provideScrapersForNode({ fs, llm, executables }),
6772
- script: await $provideScriptingForNode({}),
6855
+ scrapers,
6856
+ script,
6857
+ fetch,
6858
+ userInterface,
6773
6859
  };
6774
6860
  return tools;
6775
6861
  }
@@ -6779,9 +6865,38 @@
6779
6865
  response.setHeader('X-Powered-By', 'Promptbook engine');
6780
6866
  next();
6781
6867
  });
6868
+ const swaggerOptions = {
6869
+ definition: {
6870
+ openapi: '3.0.0',
6871
+ info: {
6872
+ title: 'Promptbook Remote Server API',
6873
+ version: '1.0.0',
6874
+ description: 'API documentation for the Promptbook Remote Server',
6875
+ },
6876
+ servers: [
6877
+ {
6878
+ url: `http://localhost:${port}${rootPath}`,
6879
+ // <- TODO: !!!!! Probbably: Pass `remoteServerUrl` instead of `port` and `rootPath`
6880
+ },
6881
+ ],
6882
+ },
6883
+ apis: ['./src/remote-server/**/*.ts'], // Adjust path as needed
6884
+ };
6885
+ const swaggerSpec = swaggerJsdoc__default["default"](swaggerOptions);
6886
+ app.use([`/api-docs`, `${rootPath}/api-docs`], swaggerUi__default["default"].serve, swaggerUi__default["default"].setup(swaggerSpec));
6782
6887
  const runningExecutionTasks = [];
6783
6888
  // <- TODO: [🤬] Identify the users
6784
6889
  // TODO: [🧠] Do here some garbage collection of finished tasks
6890
+ /**
6891
+ * @swagger
6892
+ * /:
6893
+ * get:
6894
+ * summary: Get server details
6895
+ * description: Returns details about the Promptbook server.
6896
+ * responses:
6897
+ * 200:
6898
+ * description: Server details in markdown format.
6899
+ */
6785
6900
  app.get(['/', rootPath], async (request, response) => {
6786
6901
  var _a;
6787
6902
  if ((_a = request.url) === null || _a === void 0 ? void 0 : _a.includes('socket.io')) {
@@ -6818,9 +6933,12 @@
6818
6933
 
6819
6934
  ## Paths
6820
6935
 
6821
- ${block(app._router.stack
6822
- .map(({ route }) => (route === null || route === void 0 ? void 0 : route.path) || null)
6823
- .filter((path) => path !== null)
6936
+ ${block([
6937
+ ...app._router.stack
6938
+ .map(({ route }) => (route === null || route === void 0 ? void 0 : route.path) || null)
6939
+ .filter((path) => path !== null),
6940
+ '/api-docs',
6941
+ ]
6824
6942
  .map((path) => `- ${path}`)
6825
6943
  .join('\n'))}
6826
6944
 
@@ -6838,8 +6956,94 @@
6838
6956
  https://github.com/webgptorg/promptbook
6839
6957
  `));
6840
6958
  });
6841
- // TODO: !!!!!! Add login route
6842
- app.get(`${rootPath}/books`, async (request, response) => {
6959
+ /**
6960
+ * @swagger
6961
+ *
6962
+ * /login:
6963
+ * post:
6964
+ * summary: Login to the server
6965
+ * description: Login to the server and get identification.
6966
+ * requestBody:
6967
+ * required: true
6968
+ * content:
6969
+ * application/json:
6970
+ * schema:
6971
+ * type: object
6972
+ * properties:
6973
+ * username:
6974
+ * type: string
6975
+ * password:
6976
+ * type: string
6977
+ * appId:
6978
+ * type: string
6979
+ * responses:
6980
+ * 200:
6981
+ * description: Successful login
6982
+ * content:
6983
+ * application/json:
6984
+ * schema:
6985
+ * type: object
6986
+ * properties:
6987
+ * identification:
6988
+ * type: object
6989
+ */
6990
+ app.post([`/login`, `${rootPath}/login`], async (request, response) => {
6991
+ if (!isApplicationModeAllowed || login === null) {
6992
+ response.status(400).send('Application mode is not allowed');
6993
+ return;
6994
+ }
6995
+ try {
6996
+ const username = request.body.username;
6997
+ const password = request.body.password;
6998
+ const appId = request.body.appId;
6999
+ const { isSuccess, error, message, identification } = await login({
7000
+ username,
7001
+ password,
7002
+ appId,
7003
+ rawRequest: request,
7004
+ rawResponse: response,
7005
+ });
7006
+ response.status(201).send({
7007
+ isSuccess,
7008
+ message,
7009
+ error: error ? serializeError(error) : undefined,
7010
+ identification,
7011
+ });
7012
+ return;
7013
+ }
7014
+ catch (error) {
7015
+ assertsError(error);
7016
+ if (error instanceof AuthenticationError) {
7017
+ response.status(401).send({
7018
+ isSuccess: false,
7019
+ message: error.message,
7020
+ error: serializeError(error),
7021
+ });
7022
+ }
7023
+ console.warn(`Login function thrown different error than AuthenticationError`, {
7024
+ error,
7025
+ serializedError: serializeError(error),
7026
+ });
7027
+ response.status(400).send({ error: serializeError(error) });
7028
+ }
7029
+ });
7030
+ /**
7031
+ * @swagger
7032
+ * /books:
7033
+ * get:
7034
+ * summary: List all books
7035
+ * description: Returns a list of all available books in the collection.
7036
+ * responses:
7037
+ * 200:
7038
+ * description: A list of books.
7039
+ * content:
7040
+ * application/json:
7041
+ * schema:
7042
+ * type: array
7043
+ * items:
7044
+ * type: string
7045
+ */
7046
+ app.get([`/books`, `${rootPath}/books`], async (request, response) => {
6843
7047
  if (collection === null) {
6844
7048
  response.status(500).send('No collection available');
6845
7049
  return;
@@ -6849,7 +7053,30 @@
6849
7053
  response.send(pipelines);
6850
7054
  });
6851
7055
  // TODO: [🧠] Is it secure / good idea to expose source codes of hosted books
6852
- app.get(`${rootPath}/books/*`, async (request, response) => {
7056
+ /**
7057
+ * @swagger
7058
+ * /books/{bookId}:
7059
+ * get:
7060
+ * summary: Get book content
7061
+ * description: Returns the content of a specific book.
7062
+ * parameters:
7063
+ * - in: path
7064
+ * name: bookId
7065
+ * required: true
7066
+ * schema:
7067
+ * type: string
7068
+ * description: The ID of the book to retrieve.
7069
+ * responses:
7070
+ * 200:
7071
+ * description: The content of the book.
7072
+ * content:
7073
+ * text/markdown:
7074
+ * schema:
7075
+ * type: string
7076
+ * 404:
7077
+ * description: Book not found.
7078
+ */
7079
+ app.get([`/books/*`, `${rootPath}/books/*`], async (request, response) => {
6853
7080
  try {
6854
7081
  if (collection === null) {
6855
7082
  response.status(500).send('No collection nor books available');
@@ -6868,9 +7095,7 @@
6868
7095
  .send(source.content);
6869
7096
  }
6870
7097
  catch (error) {
6871
- if (!(error instanceof Error)) {
6872
- throw error;
6873
- }
7098
+ assertsError(error);
6874
7099
  response
6875
7100
  .status(404)
6876
7101
  .send({ error: serializeError(error) });
@@ -6903,10 +7128,26 @@
6903
7128
  };
6904
7129
  }
6905
7130
  }
6906
- app.get(`${rootPath}/executions`, async (request, response) => {
7131
+ /**
7132
+ * @swagger
7133
+ * /executions:
7134
+ * get:
7135
+ * summary: List all executions
7136
+ * description: Returns a list of all running execution tasks.
7137
+ * responses:
7138
+ * 200:
7139
+ * description: A list of execution tasks.
7140
+ * content:
7141
+ * application/json:
7142
+ * schema:
7143
+ * type: array
7144
+ * items:
7145
+ * type: object
7146
+ */
7147
+ app.get([`/executions`, `${rootPath}/executions`], async (request, response) => {
6907
7148
  response.send(runningExecutionTasks.map((runningExecutionTask) => exportExecutionTask(runningExecutionTask, false)));
6908
7149
  });
6909
- app.get(`${rootPath}/executions/last`, async (request, response) => {
7150
+ app.get([`/executions/last`, `${rootPath}/executions/last`], async (request, response) => {
6910
7151
  // TODO: [🤬] Filter only for user
6911
7152
  if (runningExecutionTasks.length === 0) {
6912
7153
  response.status(404).send('No execution tasks found');
@@ -6915,7 +7156,7 @@
6915
7156
  const lastExecutionTask = runningExecutionTasks[runningExecutionTasks.length - 1];
6916
7157
  response.send(exportExecutionTask(lastExecutionTask, true));
6917
7158
  });
6918
- app.get(`${rootPath}/executions/:taskId`, async (request, response) => {
7159
+ app.get([`/executions/:taskId`, `${rootPath}/executions/:taskId`], async (request, response) => {
6919
7160
  const { taskId } = request.params;
6920
7161
  // TODO: [🤬] Filter only for user
6921
7162
  const executionTask = runningExecutionTasks.find((executionTask) => executionTask.taskId === taskId);
@@ -6927,7 +7168,36 @@
6927
7168
  }
6928
7169
  response.send(exportExecutionTask(executionTask, true));
6929
7170
  });
6930
- app.post(`${rootPath}/executions/new`, async (request, response) => {
7171
+ /**
7172
+ * @swagger
7173
+ * /executions/new:
7174
+ * post:
7175
+ * summary: Start a new execution
7176
+ * description: Starts a new execution task for a given pipeline.
7177
+ * requestBody:
7178
+ * required: true
7179
+ * content:
7180
+ * application/json:
7181
+ * schema:
7182
+ * type: object
7183
+ * properties:
7184
+ * pipelineUrl:
7185
+ * type: string
7186
+ * inputParameters:
7187
+ * type: object
7188
+ * identification:
7189
+ * type: object
7190
+ * responses:
7191
+ * 200:
7192
+ * description: The newly created execution task.
7193
+ * content:
7194
+ * application/json:
7195
+ * schema:
7196
+ * type: object
7197
+ * 400:
7198
+ * description: Invalid input.
7199
+ */
7200
+ app.post([`/executions/new`, `${rootPath}/executions/new`], async (request, response) => {
6931
7201
  try {
6932
7202
  const { inputParameters, identification /* <- [🤬] */ } = request.body;
6933
7203
  const pipelineUrl = request.body.pipelineUrl || request.body.book;
@@ -6964,12 +7234,16 @@
6964
7234
  */
6965
7235
  }
6966
7236
  catch (error) {
6967
- if (!(error instanceof Error)) {
6968
- throw error;
6969
- }
7237
+ assertsError(error);
6970
7238
  response.status(400).send({ error: serializeError(error) });
6971
7239
  }
6972
7240
  });
7241
+ /**
7242
+ * Catch-all handler for unmatched routes
7243
+ */
7244
+ app.use((request, response) => {
7245
+ response.status(404).send(`URL "${request.originalUrl}" was not found on Promptbook server.`);
7246
+ });
6973
7247
  const httpServer = http__default["default"].createServer(app);
6974
7248
  const server = new socket_io.Server(httpServer, {
6975
7249
  path: socketioPath,
@@ -7030,9 +7304,7 @@
7030
7304
  socket.emit('prompt-response', { promptResult } /* <- Note: [🤛] */);
7031
7305
  }
7032
7306
  catch (error) {
7033
- if (!(error instanceof Error)) {
7034
- throw error;
7035
- }
7307
+ assertsError(error);
7036
7308
  socket.emit('error', serializeError(error) /* <- Note: [🤛] */);
7037
7309
  }
7038
7310
  finally {
@@ -7054,9 +7326,7 @@
7054
7326
  socket.emit('listModels-response', { models } /* <- Note: [🤛] */);
7055
7327
  }
7056
7328
  catch (error) {
7057
- if (!(error instanceof Error)) {
7058
- throw error;
7059
- }
7329
+ assertsError(error);
7060
7330
  socket.emit('error', serializeError(error));
7061
7331
  }
7062
7332
  finally {
@@ -7077,9 +7347,7 @@
7077
7347
  socket.emit('preparePipeline-response', { preparedPipeline } /* <- Note: [🤛] */);
7078
7348
  }
7079
7349
  catch (error) {
7080
- if (!(error instanceof Error)) {
7081
- throw error;
7082
- }
7350
+ assertsError(error);
7083
7351
  socket.emit('error', serializeError(error));
7084
7352
  // <- TODO: [🚋] There is a problem with the remote server handling errors and sending them back to the client
7085
7353
  }
@@ -7104,6 +7372,15 @@
7104
7372
  }
7105
7373
  let isDestroyed = false;
7106
7374
  return {
7375
+ get httpServer() {
7376
+ return httpServer;
7377
+ },
7378
+ get expressApp() {
7379
+ return app;
7380
+ },
7381
+ get socketIoServer() {
7382
+ return server;
7383
+ },
7107
7384
  get isDestroyed() {
7108
7385
  return isDestroyed;
7109
7386
  },
@@ -7119,7 +7396,6 @@
7119
7396
  }
7120
7397
  /**
7121
7398
  * TODO: !! Add CORS and security - probbably via `helmet`
7122
- * TODO: [👩🏾‍🤝‍🧑🏾] Allow to pass custom fetch function here - PromptbookFetch
7123
7399
  * TODO: Split this file into multiple functions - handler for each request
7124
7400
  * TODO: Maybe use `$exportJson`
7125
7401
  * TODO: [🧠][🛍] Maybe not `isAnonymous: boolean` BUT `mode: 'ANONYMOUS'|'COLLECTION'`