@promptbook/remote-server 0.89.0-8 → 0.89.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -11
- package/esm/index.es.js +570 -420
- package/esm/index.es.js.map +1 -1
- package/esm/typings/servers.d.ts +40 -0
- package/esm/typings/src/_packages/core.index.d.ts +12 -4
- package/esm/typings/src/_packages/remote-client.index.d.ts +6 -6
- package/esm/typings/src/_packages/remote-server.index.d.ts +6 -6
- package/esm/typings/src/_packages/types.index.d.ts +24 -14
- package/esm/typings/src/_packages/utils.index.d.ts +4 -0
- package/esm/typings/src/cli/cli-commands/login.d.ts +0 -1
- package/esm/typings/src/cli/common/$provideLlmToolsForCli.d.ts +16 -3
- package/esm/typings/src/cli/test/ptbk.d.ts +1 -1
- package/esm/typings/src/commands/EXPECT/expectCommandParser.d.ts +2 -0
- package/esm/typings/src/config.d.ts +10 -19
- package/esm/typings/src/errors/0-index.d.ts +8 -2
- package/esm/typings/src/errors/PipelineExecutionError.d.ts +1 -1
- package/esm/typings/src/errors/PromptbookFetchError.d.ts +9 -0
- package/esm/typings/src/errors/WrappedError.d.ts +10 -0
- package/esm/typings/src/errors/assertsError.d.ts +11 -0
- package/esm/typings/src/execution/PromptbookFetch.d.ts +1 -1
- package/esm/typings/src/formats/csv/utils/isValidCsvString.d.ts +9 -0
- package/esm/typings/src/formats/csv/utils/isValidCsvString.test.d.ts +1 -0
- package/esm/typings/src/formats/json/utils/isValidJsonString.d.ts +3 -0
- package/esm/typings/src/formats/xml/utils/isValidXmlString.d.ts +9 -0
- package/esm/typings/src/formats/xml/utils/isValidXmlString.test.d.ts +1 -0
- package/esm/typings/src/llm-providers/_common/register/$provideEnvFilename.d.ts +12 -0
- package/esm/typings/src/llm-providers/_common/register/$provideLlmToolsConfigurationFromEnv.d.ts +2 -8
- package/esm/typings/src/llm-providers/_common/register/$provideLlmToolsForTestingAndScriptsAndPlayground.d.ts +2 -0
- package/esm/typings/src/llm-providers/_common/register/$provideLlmToolsForWizzardOrCli.d.ts +15 -4
- package/esm/typings/src/llm-providers/_common/register/$provideLlmToolsFromEnv.d.ts +1 -0
- package/esm/typings/src/remote-server/openapi-types.d.ts +284 -0
- package/esm/typings/src/remote-server/openapi.d.ts +187 -0
- package/esm/typings/src/remote-server/socket-types/_subtypes/{PromptbookServer_Identification.d.ts → Identification.d.ts} +9 -3
- package/esm/typings/src/remote-server/socket-types/_subtypes/identificationToPromptbookToken.d.ts +11 -0
- package/esm/typings/src/remote-server/socket-types/_subtypes/promptbookTokenToIdentification.d.ts +10 -0
- package/esm/typings/src/remote-server/socket-types/listModels/PromptbookServer_ListModels_Request.d.ts +2 -2
- package/esm/typings/src/remote-server/socket-types/prepare/PromptbookServer_PreparePipeline_Request.d.ts +2 -2
- package/esm/typings/src/remote-server/socket-types/prompt/PromptbookServer_Prompt_Request.d.ts +2 -2
- package/esm/typings/src/remote-server/startRemoteServer.d.ts +1 -2
- package/esm/typings/src/remote-server/types/RemoteClientOptions.d.ts +2 -2
- package/esm/typings/src/remote-server/types/RemoteServerOptions.d.ts +57 -38
- package/esm/typings/src/scrapers/_common/utils/{scraperFetch.d.ts → promptbookFetch.d.ts} +2 -2
- package/esm/typings/src/storage/env-storage/$EnvStorage.d.ts +40 -0
- package/esm/typings/src/types/typeAliases.d.ts +26 -0
- package/package.json +11 -7
- package/umd/index.umd.js +492 -324
- package/umd/index.umd.js.map +1 -1
- package/esm/typings/src/cli/test/ptbk2.d.ts +0 -5
- package/esm/typings/src/playground/BrjappConnector.d.ts +0 -67
- package/esm/typings/src/playground/brjapp-api-schema.d.ts +0 -12879
package/esm/index.es.js
CHANGED
|
@@ -2,8 +2,8 @@ import colors from 'colors';
|
|
|
2
2
|
import express from 'express';
|
|
3
3
|
import http from 'http';
|
|
4
4
|
import { Server } from 'socket.io';
|
|
5
|
-
import spaceTrim
|
|
6
|
-
import
|
|
5
|
+
import spaceTrim, { spaceTrim as spaceTrim$1 } from 'spacetrim';
|
|
6
|
+
import * as OpenApiValidator from 'express-openapi-validator';
|
|
7
7
|
import swaggerUi from 'swagger-ui-express';
|
|
8
8
|
import { forTime } from 'waitasecond';
|
|
9
9
|
import { randomBytes } from 'crypto';
|
|
@@ -33,7 +33,7 @@ const BOOK_LANGUAGE_VERSION = '1.0.0';
|
|
|
33
33
|
* @generated
|
|
34
34
|
* @see https://github.com/webgptorg/promptbook
|
|
35
35
|
*/
|
|
36
|
-
const PROMPTBOOK_ENGINE_VERSION = '0.89.0
|
|
36
|
+
const PROMPTBOOK_ENGINE_VERSION = '0.89.0';
|
|
37
37
|
/**
|
|
38
38
|
* TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
|
|
39
39
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
@@ -87,6 +87,7 @@ const ADMIN_GITHUB_NAME = 'hejny';
|
|
|
87
87
|
* @public exported from `@promptbook/core`
|
|
88
88
|
*/
|
|
89
89
|
const CLAIM = `It's time for a paradigm shift. The future of software in plain English, French or Latin`;
|
|
90
|
+
// <- TODO: [🐊] Pick the best claim
|
|
90
91
|
/**
|
|
91
92
|
* When the title is not provided, the default title is used
|
|
92
93
|
*
|
|
@@ -119,6 +120,7 @@ const VALUE_STRINGS = {
|
|
|
119
120
|
infinity: '(infinity; ∞)',
|
|
120
121
|
negativeInfinity: '(negative infinity; -∞)',
|
|
121
122
|
unserializable: '(unserializable value)',
|
|
123
|
+
circular: '(circular JSON)',
|
|
122
124
|
};
|
|
123
125
|
/**
|
|
124
126
|
* Small number limit
|
|
@@ -158,7 +160,7 @@ const DEFAULT_MAX_PARALLEL_COUNT = 5; // <- TODO: [🤹♂️]
|
|
|
158
160
|
*/
|
|
159
161
|
const DEFAULT_MAX_EXECUTION_ATTEMPTS = 10; // <- TODO: [🤹♂️]
|
|
160
162
|
// <- TODO: [🕝] Make also `BOOKS_DIRNAME_ALTERNATIVES`
|
|
161
|
-
// TODO:
|
|
163
|
+
// TODO: Just `.promptbook` in config, hardcode subfolders like `download-cache` or `execution-cache`
|
|
162
164
|
/**
|
|
163
165
|
* Where to store the temporary downloads
|
|
164
166
|
*
|
|
@@ -213,6 +215,122 @@ true);
|
|
|
213
215
|
* TODO: [🧠][🧜♂️] Maybe join remoteServerUrl and path into single value
|
|
214
216
|
*/
|
|
215
217
|
|
|
218
|
+
/**
|
|
219
|
+
* Make error report URL for the given error
|
|
220
|
+
*
|
|
221
|
+
* @private private within the repository
|
|
222
|
+
*/
|
|
223
|
+
function getErrorReportUrl(error) {
|
|
224
|
+
const report = {
|
|
225
|
+
title: `🐜 Error report from ${NAME}`,
|
|
226
|
+
body: spaceTrim((block) => `
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
\`${error.name || 'Error'}\` has occurred in the [${NAME}], please look into it @${ADMIN_GITHUB_NAME}.
|
|
230
|
+
|
|
231
|
+
\`\`\`
|
|
232
|
+
${block(error.message || '(no error message)')}
|
|
233
|
+
\`\`\`
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
## More info:
|
|
237
|
+
|
|
238
|
+
- **Promptbook engine version:** ${PROMPTBOOK_ENGINE_VERSION}
|
|
239
|
+
- **Book language version:** ${BOOK_LANGUAGE_VERSION}
|
|
240
|
+
- **Time:** ${new Date().toISOString()}
|
|
241
|
+
|
|
242
|
+
<details>
|
|
243
|
+
<summary>Stack trace:</summary>
|
|
244
|
+
|
|
245
|
+
## Stack trace:
|
|
246
|
+
|
|
247
|
+
\`\`\`stacktrace
|
|
248
|
+
${block(error.stack || '(empty)')}
|
|
249
|
+
\`\`\`
|
|
250
|
+
</details>
|
|
251
|
+
|
|
252
|
+
`),
|
|
253
|
+
};
|
|
254
|
+
const reportUrl = new URL(`https://github.com/webgptorg/promptbook/issues/new`);
|
|
255
|
+
reportUrl.searchParams.set('labels', 'bug');
|
|
256
|
+
reportUrl.searchParams.set('assignees', ADMIN_GITHUB_NAME);
|
|
257
|
+
reportUrl.searchParams.set('title', report.title);
|
|
258
|
+
reportUrl.searchParams.set('body', report.body);
|
|
259
|
+
return reportUrl;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* This error type indicates that the error should not happen and its last check before crashing with some other error
|
|
264
|
+
*
|
|
265
|
+
* @public exported from `@promptbook/core`
|
|
266
|
+
*/
|
|
267
|
+
class UnexpectedError extends Error {
|
|
268
|
+
constructor(message) {
|
|
269
|
+
super(spaceTrim$1((block) => `
|
|
270
|
+
${block(message)}
|
|
271
|
+
|
|
272
|
+
Note: This error should not happen.
|
|
273
|
+
It's probbably a bug in the pipeline collection
|
|
274
|
+
|
|
275
|
+
Please report issue:
|
|
276
|
+
${block(getErrorReportUrl(new Error(message)).href)}
|
|
277
|
+
|
|
278
|
+
Or contact us on ${ADMIN_EMAIL}
|
|
279
|
+
|
|
280
|
+
`));
|
|
281
|
+
this.name = 'UnexpectedError';
|
|
282
|
+
Object.setPrototypeOf(this, UnexpectedError.prototype);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* This error type indicates that somewhere in the code non-Error object was thrown and it was wrapped into the `WrappedError`
|
|
288
|
+
*
|
|
289
|
+
* @public exported from `@promptbook/core`
|
|
290
|
+
*/
|
|
291
|
+
class WrappedError extends Error {
|
|
292
|
+
constructor(whatWasThrown) {
|
|
293
|
+
const tag = `[🤮]`;
|
|
294
|
+
console.error(tag, whatWasThrown);
|
|
295
|
+
super(spaceTrim$1(`
|
|
296
|
+
Non-Error object was thrown
|
|
297
|
+
|
|
298
|
+
Note: Look for ${tag} in the console for more details
|
|
299
|
+
Please report issue on ${ADMIN_EMAIL}
|
|
300
|
+
`));
|
|
301
|
+
this.name = 'WrappedError';
|
|
302
|
+
Object.setPrototypeOf(this, WrappedError.prototype);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* Helper used in catch blocks to assert that the error is an instance of `Error`
|
|
308
|
+
*
|
|
309
|
+
* @param whatWasThrown Any object that was thrown
|
|
310
|
+
* @returns Nothing if the error is an instance of `Error`
|
|
311
|
+
* @throws `WrappedError` or `UnexpectedError` if the error is not standard
|
|
312
|
+
*
|
|
313
|
+
* @private within the repository
|
|
314
|
+
*/
|
|
315
|
+
function assertsError(whatWasThrown) {
|
|
316
|
+
// Case 1: Handle error which was rethrown as `WrappedError`
|
|
317
|
+
if (whatWasThrown instanceof WrappedError) {
|
|
318
|
+
const wrappedError = whatWasThrown;
|
|
319
|
+
throw wrappedError;
|
|
320
|
+
}
|
|
321
|
+
// Case 2: Handle unexpected errors
|
|
322
|
+
if (whatWasThrown instanceof UnexpectedError) {
|
|
323
|
+
const unexpectedError = whatWasThrown;
|
|
324
|
+
throw unexpectedError;
|
|
325
|
+
}
|
|
326
|
+
// Case 3: Handle standard errors - keep them up to consumer
|
|
327
|
+
if (whatWasThrown instanceof Error) {
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
// Case 4: Handle non-standard errors - wrap them into `WrappedError` and throw
|
|
331
|
+
throw new WrappedError(whatWasThrown);
|
|
332
|
+
}
|
|
333
|
+
|
|
216
334
|
/**
|
|
217
335
|
* AuthenticationError is thrown from login function which is dependency of remote server
|
|
218
336
|
*
|
|
@@ -257,7 +375,7 @@ class PipelineExecutionError extends Error {
|
|
|
257
375
|
}
|
|
258
376
|
}
|
|
259
377
|
/**
|
|
260
|
-
* TODO:
|
|
378
|
+
* TODO: [🧠][🌂] Add id to all errors
|
|
261
379
|
*/
|
|
262
380
|
|
|
263
381
|
/**
|
|
@@ -365,7 +483,7 @@ class LimitReachedError extends Error {
|
|
|
365
483
|
*/
|
|
366
484
|
class MissingToolsError extends Error {
|
|
367
485
|
constructor(message) {
|
|
368
|
-
super(spaceTrim((block) => `
|
|
486
|
+
super(spaceTrim$1((block) => `
|
|
369
487
|
${block(message)}
|
|
370
488
|
|
|
371
489
|
Note: You have probbably forgot to provide some tools for pipeline execution or preparation
|
|
@@ -396,7 +514,7 @@ class NotFoundError extends Error {
|
|
|
396
514
|
*/
|
|
397
515
|
class NotYetImplementedError extends Error {
|
|
398
516
|
constructor(message) {
|
|
399
|
-
super(spaceTrim((block) => `
|
|
517
|
+
super(spaceTrim$1((block) => `
|
|
400
518
|
${block(message)}
|
|
401
519
|
|
|
402
520
|
Note: This feature is not implemented yet but it will be soon.
|
|
@@ -455,70 +573,15 @@ class PipelineUrlError extends Error {
|
|
|
455
573
|
}
|
|
456
574
|
|
|
457
575
|
/**
|
|
458
|
-
*
|
|
459
|
-
*
|
|
460
|
-
* @private private within the repository
|
|
461
|
-
*/
|
|
462
|
-
function getErrorReportUrl(error) {
|
|
463
|
-
const report = {
|
|
464
|
-
title: `🐜 Error report from ${NAME}`,
|
|
465
|
-
body: spaceTrim$1((block) => `
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
\`${error.name || 'Error'}\` has occurred in the [${NAME}], please look into it @${ADMIN_GITHUB_NAME}.
|
|
469
|
-
|
|
470
|
-
\`\`\`
|
|
471
|
-
${block(error.message || '(no error message)')}
|
|
472
|
-
\`\`\`
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
## More info:
|
|
476
|
-
|
|
477
|
-
- **Promptbook engine version:** ${PROMPTBOOK_ENGINE_VERSION}
|
|
478
|
-
- **Book language version:** ${BOOK_LANGUAGE_VERSION}
|
|
479
|
-
- **Time:** ${new Date().toISOString()}
|
|
480
|
-
|
|
481
|
-
<details>
|
|
482
|
-
<summary>Stack trace:</summary>
|
|
483
|
-
|
|
484
|
-
## Stack trace:
|
|
485
|
-
|
|
486
|
-
\`\`\`stacktrace
|
|
487
|
-
${block(error.stack || '(empty)')}
|
|
488
|
-
\`\`\`
|
|
489
|
-
</details>
|
|
490
|
-
|
|
491
|
-
`),
|
|
492
|
-
};
|
|
493
|
-
const reportUrl = new URL(`https://github.com/webgptorg/promptbook/issues/new`);
|
|
494
|
-
reportUrl.searchParams.set('labels', 'bug');
|
|
495
|
-
reportUrl.searchParams.set('assignees', ADMIN_GITHUB_NAME);
|
|
496
|
-
reportUrl.searchParams.set('title', report.title);
|
|
497
|
-
reportUrl.searchParams.set('body', report.body);
|
|
498
|
-
return reportUrl;
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
/**
|
|
502
|
-
* This error type indicates that the error should not happen and its last check before crashing with some other error
|
|
576
|
+
* Error thrown when a fetch request fails
|
|
503
577
|
*
|
|
504
578
|
* @public exported from `@promptbook/core`
|
|
505
579
|
*/
|
|
506
|
-
class
|
|
580
|
+
class PromptbookFetchError extends Error {
|
|
507
581
|
constructor(message) {
|
|
508
|
-
super(
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
Note: This error should not happen.
|
|
512
|
-
It's probbably a bug in the pipeline collection
|
|
513
|
-
|
|
514
|
-
Please report issue:
|
|
515
|
-
${block(getErrorReportUrl(new Error(message)).href)}
|
|
516
|
-
|
|
517
|
-
Or contact us on ${ADMIN_EMAIL}
|
|
518
|
-
|
|
519
|
-
`));
|
|
520
|
-
this.name = 'UnexpectedError';
|
|
521
|
-
Object.setPrototypeOf(this, UnexpectedError.prototype);
|
|
582
|
+
super(message);
|
|
583
|
+
this.name = 'PromptbookFetchError';
|
|
584
|
+
Object.setPrototypeOf(this, PromptbookFetchError.prototype);
|
|
522
585
|
}
|
|
523
586
|
}
|
|
524
587
|
|
|
@@ -542,7 +605,10 @@ const PROMPTBOOK_ERRORS = {
|
|
|
542
605
|
PipelineExecutionError,
|
|
543
606
|
PipelineLogicError,
|
|
544
607
|
PipelineUrlError,
|
|
608
|
+
AuthenticationError,
|
|
609
|
+
PromptbookFetchError,
|
|
545
610
|
UnexpectedError,
|
|
611
|
+
WrappedError,
|
|
546
612
|
// TODO: [🪑]> VersionMismatchError,
|
|
547
613
|
};
|
|
548
614
|
/**
|
|
@@ -559,7 +625,6 @@ const COMMON_JAVASCRIPT_ERRORS = {
|
|
|
559
625
|
TypeError,
|
|
560
626
|
URIError,
|
|
561
627
|
AggregateError,
|
|
562
|
-
AuthenticationError,
|
|
563
628
|
/*
|
|
564
629
|
Note: Not widely supported
|
|
565
630
|
> InternalError,
|
|
@@ -591,7 +656,7 @@ function serializeError(error) {
|
|
|
591
656
|
const { name, message, stack } = error;
|
|
592
657
|
const { id } = error;
|
|
593
658
|
if (!Object.keys(ALL_ERRORS).includes(name)) {
|
|
594
|
-
console.error(spaceTrim
|
|
659
|
+
console.error(spaceTrim((block) => `
|
|
595
660
|
|
|
596
661
|
Cannot serialize error with name "${name}"
|
|
597
662
|
|
|
@@ -755,11 +820,11 @@ function $execCommand(options) {
|
|
|
755
820
|
console.warn(`Command "${humanReadableCommand}" exited with code ${code}`);
|
|
756
821
|
// <- TODO: [🏮] Some standard way how to transform errors into warnings and how to handle non-critical fails during the tasks
|
|
757
822
|
}
|
|
758
|
-
resolve(spaceTrim(output.join('\n')));
|
|
823
|
+
resolve(spaceTrim$1(output.join('\n')));
|
|
759
824
|
}
|
|
760
825
|
}
|
|
761
826
|
else {
|
|
762
|
-
resolve(spaceTrim(output.join('\n')));
|
|
827
|
+
resolve(spaceTrim$1(output.join('\n')));
|
|
763
828
|
}
|
|
764
829
|
};
|
|
765
830
|
commandProcess.on('close', finishWithCode);
|
|
@@ -777,7 +842,7 @@ function $execCommand(options) {
|
|
|
777
842
|
console.warn(error);
|
|
778
843
|
// <- TODO: [🏮] Some standard way how to transform errors into warnings and how to handle non-critical fails during the tasks
|
|
779
844
|
}
|
|
780
|
-
resolve(spaceTrim(output.join('\n')));
|
|
845
|
+
resolve(spaceTrim$1(output.join('\n')));
|
|
781
846
|
}
|
|
782
847
|
});
|
|
783
848
|
}
|
|
@@ -802,9 +867,7 @@ async function locateAppOnLinux({ linuxWhich, }) {
|
|
|
802
867
|
return result.trim();
|
|
803
868
|
}
|
|
804
869
|
catch (error) {
|
|
805
|
-
|
|
806
|
-
throw error;
|
|
807
|
-
}
|
|
870
|
+
assertsError(error);
|
|
808
871
|
return null;
|
|
809
872
|
}
|
|
810
873
|
}
|
|
@@ -882,9 +945,7 @@ async function locateAppOnMacOs({ macOsName, }) {
|
|
|
882
945
|
return result.trim() + toExec;
|
|
883
946
|
}
|
|
884
947
|
catch (error) {
|
|
885
|
-
|
|
886
|
-
throw error;
|
|
887
|
-
}
|
|
948
|
+
assertsError(error);
|
|
888
949
|
return null;
|
|
889
950
|
}
|
|
890
951
|
}
|
|
@@ -915,9 +976,7 @@ async function locateAppOnWindows({ appName, windowsSuffix, }) {
|
|
|
915
976
|
throw new Error(`Can not locate app ${appName} on Windows.`);
|
|
916
977
|
}
|
|
917
978
|
catch (error) {
|
|
918
|
-
|
|
919
|
-
throw error;
|
|
920
|
-
}
|
|
979
|
+
assertsError(error);
|
|
921
980
|
return null;
|
|
922
981
|
}
|
|
923
982
|
}
|
|
@@ -1114,7 +1173,7 @@ function checkSerializableAsJson(options) {
|
|
|
1114
1173
|
}
|
|
1115
1174
|
else if (typeof value === 'object') {
|
|
1116
1175
|
if (value instanceof Date) {
|
|
1117
|
-
throw new UnexpectedError(spaceTrim
|
|
1176
|
+
throw new UnexpectedError(spaceTrim((block) => `
|
|
1118
1177
|
\`${name}\` is Date
|
|
1119
1178
|
|
|
1120
1179
|
Use \`string_date_iso8601\` instead
|
|
@@ -1133,7 +1192,7 @@ function checkSerializableAsJson(options) {
|
|
|
1133
1192
|
throw new UnexpectedError(`${name} is RegExp`);
|
|
1134
1193
|
}
|
|
1135
1194
|
else if (value instanceof Error) {
|
|
1136
|
-
throw new UnexpectedError(spaceTrim
|
|
1195
|
+
throw new UnexpectedError(spaceTrim((block) => `
|
|
1137
1196
|
\`${name}\` is unserialized Error
|
|
1138
1197
|
|
|
1139
1198
|
Use function \`serializeError\`
|
|
@@ -1155,10 +1214,8 @@ function checkSerializableAsJson(options) {
|
|
|
1155
1214
|
JSON.stringify(value); // <- TODO: [0]
|
|
1156
1215
|
}
|
|
1157
1216
|
catch (error) {
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
}
|
|
1161
|
-
throw new UnexpectedError(spaceTrim$1((block) => `
|
|
1217
|
+
assertsError(error);
|
|
1218
|
+
throw new UnexpectedError(spaceTrim((block) => `
|
|
1162
1219
|
\`${name}\` is not serializable
|
|
1163
1220
|
|
|
1164
1221
|
${block(error.stack || error.message)}
|
|
@@ -1190,7 +1247,7 @@ function checkSerializableAsJson(options) {
|
|
|
1190
1247
|
}
|
|
1191
1248
|
}
|
|
1192
1249
|
else {
|
|
1193
|
-
throw new UnexpectedError(spaceTrim
|
|
1250
|
+
throw new UnexpectedError(spaceTrim((block) => `
|
|
1194
1251
|
\`${name}\` is unknown type
|
|
1195
1252
|
|
|
1196
1253
|
Additional message for \`${name}\`:
|
|
@@ -1453,7 +1510,7 @@ function validatePipeline(pipeline) {
|
|
|
1453
1510
|
if (!(error instanceof PipelineLogicError)) {
|
|
1454
1511
|
throw error;
|
|
1455
1512
|
}
|
|
1456
|
-
console.error(spaceTrim((block) => `
|
|
1513
|
+
console.error(spaceTrim$1((block) => `
|
|
1457
1514
|
Pipeline is not valid but logic errors are temporarily disabled via \`IS_PIPELINE_LOGIC_VALIDATED\`
|
|
1458
1515
|
|
|
1459
1516
|
${block(error.message)}
|
|
@@ -1480,7 +1537,7 @@ function validatePipeline_InnerFunction(pipeline) {
|
|
|
1480
1537
|
})();
|
|
1481
1538
|
if (pipeline.pipelineUrl !== undefined && !isValidPipelineUrl(pipeline.pipelineUrl)) {
|
|
1482
1539
|
// <- Note: [🚲]
|
|
1483
|
-
throw new PipelineLogicError(spaceTrim((block) => `
|
|
1540
|
+
throw new PipelineLogicError(spaceTrim$1((block) => `
|
|
1484
1541
|
Invalid promptbook URL "${pipeline.pipelineUrl}"
|
|
1485
1542
|
|
|
1486
1543
|
${block(pipelineIdentification)}
|
|
@@ -1488,7 +1545,7 @@ function validatePipeline_InnerFunction(pipeline) {
|
|
|
1488
1545
|
}
|
|
1489
1546
|
if (pipeline.bookVersion !== undefined && !isValidPromptbookVersion(pipeline.bookVersion)) {
|
|
1490
1547
|
// <- Note: [🚲]
|
|
1491
|
-
throw new PipelineLogicError(spaceTrim((block) => `
|
|
1548
|
+
throw new PipelineLogicError(spaceTrim$1((block) => `
|
|
1492
1549
|
Invalid Promptbook Version "${pipeline.bookVersion}"
|
|
1493
1550
|
|
|
1494
1551
|
${block(pipelineIdentification)}
|
|
@@ -1497,7 +1554,7 @@ function validatePipeline_InnerFunction(pipeline) {
|
|
|
1497
1554
|
// TODO: [🧠] Maybe do here some propper JSON-schema / ZOD checking
|
|
1498
1555
|
if (!Array.isArray(pipeline.parameters)) {
|
|
1499
1556
|
// TODO: [🧠] what is the correct error tp throw - maybe PromptbookSchemaError
|
|
1500
|
-
throw new ParseError(spaceTrim((block) => `
|
|
1557
|
+
throw new ParseError(spaceTrim$1((block) => `
|
|
1501
1558
|
Pipeline is valid JSON but with wrong structure
|
|
1502
1559
|
|
|
1503
1560
|
\`PipelineJson.parameters\` expected to be an array, but got ${typeof pipeline.parameters}
|
|
@@ -1508,7 +1565,7 @@ function validatePipeline_InnerFunction(pipeline) {
|
|
|
1508
1565
|
// TODO: [🧠] Maybe do here some propper JSON-schema / ZOD checking
|
|
1509
1566
|
if (!Array.isArray(pipeline.tasks)) {
|
|
1510
1567
|
// TODO: [🧠] what is the correct error tp throw - maybe PromptbookSchemaError
|
|
1511
|
-
throw new ParseError(spaceTrim((block) => `
|
|
1568
|
+
throw new ParseError(spaceTrim$1((block) => `
|
|
1512
1569
|
Pipeline is valid JSON but with wrong structure
|
|
1513
1570
|
|
|
1514
1571
|
\`PipelineJson.tasks\` expected to be an array, but got ${typeof pipeline.tasks}
|
|
@@ -1534,7 +1591,7 @@ function validatePipeline_InnerFunction(pipeline) {
|
|
|
1534
1591
|
// Note: Check each parameter individually
|
|
1535
1592
|
for (const parameter of pipeline.parameters) {
|
|
1536
1593
|
if (parameter.isInput && parameter.isOutput) {
|
|
1537
|
-
throw new PipelineLogicError(spaceTrim((block) => `
|
|
1594
|
+
throw new PipelineLogicError(spaceTrim$1((block) => `
|
|
1538
1595
|
|
|
1539
1596
|
Parameter \`{${parameter.name}}\` can not be both input and output
|
|
1540
1597
|
|
|
@@ -1545,7 +1602,7 @@ function validatePipeline_InnerFunction(pipeline) {
|
|
|
1545
1602
|
if (!parameter.isInput &&
|
|
1546
1603
|
!parameter.isOutput &&
|
|
1547
1604
|
!pipeline.tasks.some((task) => task.dependentParameterNames.includes(parameter.name))) {
|
|
1548
|
-
throw new PipelineLogicError(spaceTrim((block) => `
|
|
1605
|
+
throw new PipelineLogicError(spaceTrim$1((block) => `
|
|
1549
1606
|
Parameter \`{${parameter.name}}\` is created but not used
|
|
1550
1607
|
|
|
1551
1608
|
You can declare {${parameter.name}} as output parameter by adding in the header:
|
|
@@ -1557,7 +1614,7 @@ function validatePipeline_InnerFunction(pipeline) {
|
|
|
1557
1614
|
}
|
|
1558
1615
|
// Note: Testing that parameter is either input or result of some task
|
|
1559
1616
|
if (!parameter.isInput && !pipeline.tasks.some((task) => task.resultingParameterName === parameter.name)) {
|
|
1560
|
-
throw new PipelineLogicError(spaceTrim((block) => `
|
|
1617
|
+
throw new PipelineLogicError(spaceTrim$1((block) => `
|
|
1561
1618
|
Parameter \`{${parameter.name}}\` is declared but not defined
|
|
1562
1619
|
|
|
1563
1620
|
You can do one of these:
|
|
@@ -1573,14 +1630,14 @@ function validatePipeline_InnerFunction(pipeline) {
|
|
|
1573
1630
|
// Note: Checking each task individually
|
|
1574
1631
|
for (const task of pipeline.tasks) {
|
|
1575
1632
|
if (definedParameters.has(task.resultingParameterName)) {
|
|
1576
|
-
throw new PipelineLogicError(spaceTrim((block) => `
|
|
1633
|
+
throw new PipelineLogicError(spaceTrim$1((block) => `
|
|
1577
1634
|
Parameter \`{${task.resultingParameterName}}\` is defined multiple times
|
|
1578
1635
|
|
|
1579
1636
|
${block(pipelineIdentification)}
|
|
1580
1637
|
`));
|
|
1581
1638
|
}
|
|
1582
1639
|
if (RESERVED_PARAMETER_NAMES.includes(task.resultingParameterName)) {
|
|
1583
|
-
throw new PipelineLogicError(spaceTrim((block) => `
|
|
1640
|
+
throw new PipelineLogicError(spaceTrim$1((block) => `
|
|
1584
1641
|
Parameter name {${task.resultingParameterName}} is reserved, please use different name
|
|
1585
1642
|
|
|
1586
1643
|
${block(pipelineIdentification)}
|
|
@@ -1590,7 +1647,7 @@ function validatePipeline_InnerFunction(pipeline) {
|
|
|
1590
1647
|
if (task.jokerParameterNames && task.jokerParameterNames.length > 0) {
|
|
1591
1648
|
if (!task.format &&
|
|
1592
1649
|
!task.expectations /* <- TODO: Require at least 1 -> min <- expectation to use jokers */) {
|
|
1593
|
-
throw new PipelineLogicError(spaceTrim((block) => `
|
|
1650
|
+
throw new PipelineLogicError(spaceTrim$1((block) => `
|
|
1594
1651
|
Joker parameters are used for {${task.resultingParameterName}} but no expectations are defined
|
|
1595
1652
|
|
|
1596
1653
|
${block(pipelineIdentification)}
|
|
@@ -1598,7 +1655,7 @@ function validatePipeline_InnerFunction(pipeline) {
|
|
|
1598
1655
|
}
|
|
1599
1656
|
for (const joker of task.jokerParameterNames) {
|
|
1600
1657
|
if (!task.dependentParameterNames.includes(joker)) {
|
|
1601
|
-
throw new PipelineLogicError(spaceTrim((block) => `
|
|
1658
|
+
throw new PipelineLogicError(spaceTrim$1((block) => `
|
|
1602
1659
|
Parameter \`{${joker}}\` is used for {${task.resultingParameterName}} as joker but not in \`dependentParameterNames\`
|
|
1603
1660
|
|
|
1604
1661
|
${block(pipelineIdentification)}
|
|
@@ -1609,21 +1666,21 @@ function validatePipeline_InnerFunction(pipeline) {
|
|
|
1609
1666
|
if (task.expectations) {
|
|
1610
1667
|
for (const [unit, { min, max }] of Object.entries(task.expectations)) {
|
|
1611
1668
|
if (min !== undefined && max !== undefined && min > max) {
|
|
1612
|
-
throw new PipelineLogicError(spaceTrim((block) => `
|
|
1669
|
+
throw new PipelineLogicError(spaceTrim$1((block) => `
|
|
1613
1670
|
Min expectation (=${min}) of ${unit} is higher than max expectation (=${max})
|
|
1614
1671
|
|
|
1615
1672
|
${block(pipelineIdentification)}
|
|
1616
1673
|
`));
|
|
1617
1674
|
}
|
|
1618
1675
|
if (min !== undefined && min < 0) {
|
|
1619
|
-
throw new PipelineLogicError(spaceTrim((block) => `
|
|
1676
|
+
throw new PipelineLogicError(spaceTrim$1((block) => `
|
|
1620
1677
|
Min expectation of ${unit} must be zero or positive
|
|
1621
1678
|
|
|
1622
1679
|
${block(pipelineIdentification)}
|
|
1623
1680
|
`));
|
|
1624
1681
|
}
|
|
1625
1682
|
if (max !== undefined && max <= 0) {
|
|
1626
|
-
throw new PipelineLogicError(spaceTrim((block) => `
|
|
1683
|
+
throw new PipelineLogicError(spaceTrim$1((block) => `
|
|
1627
1684
|
Max expectation of ${unit} must be positive
|
|
1628
1685
|
|
|
1629
1686
|
${block(pipelineIdentification)}
|
|
@@ -1645,7 +1702,7 @@ function validatePipeline_InnerFunction(pipeline) {
|
|
|
1645
1702
|
while (unresovedTasks.length > 0) {
|
|
1646
1703
|
if (loopLimit-- < 0) {
|
|
1647
1704
|
// Note: Really UnexpectedError not LimitReachedError - this should not happen and be caught below
|
|
1648
|
-
throw new UnexpectedError(spaceTrim((block) => `
|
|
1705
|
+
throw new UnexpectedError(spaceTrim$1((block) => `
|
|
1649
1706
|
Loop limit reached during detection of circular dependencies in \`validatePipeline\`
|
|
1650
1707
|
|
|
1651
1708
|
${block(pipelineIdentification)}
|
|
@@ -1655,7 +1712,7 @@ function validatePipeline_InnerFunction(pipeline) {
|
|
|
1655
1712
|
if (currentlyResovedTasks.length === 0) {
|
|
1656
1713
|
throw new PipelineLogicError(
|
|
1657
1714
|
// TODO: [🐎] DRY
|
|
1658
|
-
spaceTrim((block) => `
|
|
1715
|
+
spaceTrim$1((block) => `
|
|
1659
1716
|
|
|
1660
1717
|
Can not resolve some parameters:
|
|
1661
1718
|
Either you are using a parameter that is not defined, or there are some circular dependencies.
|
|
@@ -1757,6 +1814,9 @@ function isPipelinePrepared(pipeline) {
|
|
|
1757
1814
|
/**
|
|
1758
1815
|
* Function isValidJsonString will tell you if the string is valid JSON or not
|
|
1759
1816
|
*
|
|
1817
|
+
* @param value The string to check
|
|
1818
|
+
* @returns True if the string is a valid JSON string, false otherwise
|
|
1819
|
+
*
|
|
1760
1820
|
* @public exported from `@promptbook/utils`
|
|
1761
1821
|
*/
|
|
1762
1822
|
function isValidJsonString(value /* <- [👨⚖️] */) {
|
|
@@ -1765,9 +1825,7 @@ function isValidJsonString(value /* <- [👨⚖️] */) {
|
|
|
1765
1825
|
return true;
|
|
1766
1826
|
}
|
|
1767
1827
|
catch (error) {
|
|
1768
|
-
|
|
1769
|
-
throw error;
|
|
1770
|
-
}
|
|
1828
|
+
assertsError(error);
|
|
1771
1829
|
if (error.message.includes('Unexpected token')) {
|
|
1772
1830
|
return false;
|
|
1773
1831
|
}
|
|
@@ -1819,7 +1877,7 @@ function deserializeError(error) {
|
|
|
1819
1877
|
message = `${name}: ${message}`;
|
|
1820
1878
|
}
|
|
1821
1879
|
if (stack !== undefined && stack !== '') {
|
|
1822
|
-
message = spaceTrim
|
|
1880
|
+
message = spaceTrim((block) => `
|
|
1823
1881
|
${block(message)}
|
|
1824
1882
|
|
|
1825
1883
|
Original stack trace:
|
|
@@ -1856,11 +1914,11 @@ function assertsTaskSuccessful(executionResult) {
|
|
|
1856
1914
|
throw deserializeError(errors[0]);
|
|
1857
1915
|
}
|
|
1858
1916
|
else {
|
|
1859
|
-
throw new PipelineExecutionError(spaceTrim((block) => `
|
|
1917
|
+
throw new PipelineExecutionError(spaceTrim$1((block) => `
|
|
1860
1918
|
Multiple errors occurred during Promptbook execution
|
|
1861
1919
|
|
|
1862
1920
|
${block(errors
|
|
1863
|
-
.map(({ name, stack, message }, index) => spaceTrim((block) => `
|
|
1921
|
+
.map(({ name, stack, message }, index) => spaceTrim$1((block) => `
|
|
1864
1922
|
${name} ${index + 1}:
|
|
1865
1923
|
${block(stack || message)}
|
|
1866
1924
|
`))
|
|
@@ -1905,8 +1963,8 @@ function createTask(options) {
|
|
|
1905
1963
|
updatedAt = new Date();
|
|
1906
1964
|
errors.push(...executionResult.errors);
|
|
1907
1965
|
warnings.push(...executionResult.warnings);
|
|
1908
|
-
// <- TODO:
|
|
1909
|
-
// TODO: [🧠]
|
|
1966
|
+
// <- TODO: [🌂] Only unique errors and warnings should be added (or filtered)
|
|
1967
|
+
// TODO: [🧠] !! errors, warning, isSuccessful are redundant both in `ExecutionTask` and `ExecutionTask.currentValue`
|
|
1910
1968
|
// Also maybe move `ExecutionTask.currentValue.usage` -> `ExecutionTask.usage`
|
|
1911
1969
|
// And delete `ExecutionTask.currentValue.preparedPipeline`
|
|
1912
1970
|
assertsTaskSuccessful(executionResult);
|
|
@@ -1916,6 +1974,7 @@ function createTask(options) {
|
|
|
1916
1974
|
partialResultSubject.next(executionResult);
|
|
1917
1975
|
}
|
|
1918
1976
|
catch (error) {
|
|
1977
|
+
assertsError(error);
|
|
1919
1978
|
status = 'ERROR';
|
|
1920
1979
|
errors.push(error);
|
|
1921
1980
|
partialResultSubject.error(error);
|
|
@@ -2218,7 +2277,7 @@ function pipelineJsonToString(pipelineJson) {
|
|
|
2218
2277
|
pipelineString += '\n\n';
|
|
2219
2278
|
pipelineString += '```' + contentLanguage;
|
|
2220
2279
|
pipelineString += '\n';
|
|
2221
|
-
pipelineString += spaceTrim
|
|
2280
|
+
pipelineString += spaceTrim(content);
|
|
2222
2281
|
// <- TODO: [main] !!3 Escape
|
|
2223
2282
|
// <- TODO: [🧠] Some clear strategy how to spaceTrim the blocks
|
|
2224
2283
|
pipelineString += '\n';
|
|
@@ -2323,7 +2382,7 @@ class SimplePipelineCollection {
|
|
|
2323
2382
|
for (const pipeline of pipelines) {
|
|
2324
2383
|
// TODO: [👠] DRY
|
|
2325
2384
|
if (pipeline.pipelineUrl === undefined) {
|
|
2326
|
-
throw new PipelineUrlError(spaceTrim(`
|
|
2385
|
+
throw new PipelineUrlError(spaceTrim$1(`
|
|
2327
2386
|
Pipeline with name "${pipeline.title}" does not have defined URL
|
|
2328
2387
|
|
|
2329
2388
|
File:
|
|
@@ -2345,7 +2404,7 @@ class SimplePipelineCollection {
|
|
|
2345
2404
|
pipelineJsonToString(unpreparePipeline(pipeline)) !==
|
|
2346
2405
|
pipelineJsonToString(unpreparePipeline(this.collection.get(pipeline.pipelineUrl)))) {
|
|
2347
2406
|
const existing = this.collection.get(pipeline.pipelineUrl);
|
|
2348
|
-
throw new PipelineUrlError(spaceTrim(`
|
|
2407
|
+
throw new PipelineUrlError(spaceTrim$1(`
|
|
2349
2408
|
Pipeline with URL ${pipeline.pipelineUrl} is already in the collection 🍎
|
|
2350
2409
|
|
|
2351
2410
|
Conflicting files:
|
|
@@ -2377,13 +2436,13 @@ class SimplePipelineCollection {
|
|
|
2377
2436
|
const pipeline = this.collection.get(url);
|
|
2378
2437
|
if (!pipeline) {
|
|
2379
2438
|
if (this.listPipelines().length === 0) {
|
|
2380
|
-
throw new NotFoundError(spaceTrim(`
|
|
2439
|
+
throw new NotFoundError(spaceTrim$1(`
|
|
2381
2440
|
Pipeline with url "${url}" not found
|
|
2382
2441
|
|
|
2383
2442
|
No pipelines available
|
|
2384
2443
|
`));
|
|
2385
2444
|
}
|
|
2386
|
-
throw new NotFoundError(spaceTrim((block) => `
|
|
2445
|
+
throw new NotFoundError(spaceTrim$1((block) => `
|
|
2387
2446
|
Pipeline with url "${url}" not found
|
|
2388
2447
|
|
|
2389
2448
|
Available pipelines:
|
|
@@ -2726,14 +2785,15 @@ class MultipleLlmExecutionTools {
|
|
|
2726
2785
|
}
|
|
2727
2786
|
}
|
|
2728
2787
|
catch (error) {
|
|
2729
|
-
|
|
2788
|
+
assertsError(error);
|
|
2789
|
+
if (error instanceof UnexpectedError) {
|
|
2730
2790
|
throw error;
|
|
2731
2791
|
}
|
|
2732
2792
|
errors.push({ llmExecutionTools, error });
|
|
2733
2793
|
}
|
|
2734
2794
|
}
|
|
2735
2795
|
if (errors.length === 1) {
|
|
2736
|
-
throw errors[0];
|
|
2796
|
+
throw errors[0].error;
|
|
2737
2797
|
}
|
|
2738
2798
|
else if (errors.length > 1) {
|
|
2739
2799
|
throw new PipelineExecutionError(
|
|
@@ -2741,7 +2801,7 @@ class MultipleLlmExecutionTools {
|
|
|
2741
2801
|
// 1) OpenAI throw PipelineExecutionError: Parameter `{knowledge}` is not defined
|
|
2742
2802
|
// 2) AnthropicClaude throw PipelineExecutionError: Parameter `{knowledge}` is not defined
|
|
2743
2803
|
// 3) ...
|
|
2744
|
-
spaceTrim
|
|
2804
|
+
spaceTrim((block) => `
|
|
2745
2805
|
All execution tools failed:
|
|
2746
2806
|
|
|
2747
2807
|
${block(errors
|
|
@@ -2754,7 +2814,7 @@ class MultipleLlmExecutionTools {
|
|
|
2754
2814
|
throw new PipelineExecutionError(`You have not provided any \`LlmExecutionTools\``);
|
|
2755
2815
|
}
|
|
2756
2816
|
else {
|
|
2757
|
-
throw new PipelineExecutionError(spaceTrim
|
|
2817
|
+
throw new PipelineExecutionError(spaceTrim((block) => `
|
|
2758
2818
|
You have not provided any \`LlmExecutionTools\` that support model variant "${prompt.modelRequirements.modelVariant}"
|
|
2759
2819
|
|
|
2760
2820
|
Available \`LlmExecutionTools\`:
|
|
@@ -2787,7 +2847,7 @@ class MultipleLlmExecutionTools {
|
|
|
2787
2847
|
*/
|
|
2788
2848
|
function joinLlmExecutionTools(...llmExecutionTools) {
|
|
2789
2849
|
if (llmExecutionTools.length === 0) {
|
|
2790
|
-
const warningMessage = spaceTrim
|
|
2850
|
+
const warningMessage = spaceTrim(`
|
|
2791
2851
|
You have not provided any \`LlmExecutionTools\`
|
|
2792
2852
|
This means that you won't be able to execute any prompts that require large language models like GPT-4 or Anthropic's Claude.
|
|
2793
2853
|
|
|
@@ -3078,14 +3138,14 @@ function $registeredScrapersMessage(availableScrapers) {
|
|
|
3078
3138
|
return { ...metadata, isMetadataAviailable, isInstalled, isAvilableInTools };
|
|
3079
3139
|
});
|
|
3080
3140
|
if (metadata.length === 0) {
|
|
3081
|
-
return spaceTrim
|
|
3141
|
+
return spaceTrim(`
|
|
3082
3142
|
**No scrapers are available**
|
|
3083
3143
|
|
|
3084
3144
|
This is a unexpected behavior, you are probably using some broken version of Promptbook
|
|
3085
3145
|
At least there should be available the metadata of the scrapers
|
|
3086
3146
|
`);
|
|
3087
3147
|
}
|
|
3088
|
-
return spaceTrim
|
|
3148
|
+
return spaceTrim((block) => `
|
|
3089
3149
|
Available scrapers are:
|
|
3090
3150
|
${block(metadata
|
|
3091
3151
|
.map(({ packageName, className, isMetadataAviailable, isInstalled, mimeTypes, isAvilableInBrowser, isAvilableInTools, }, i) => {
|
|
@@ -3567,17 +3627,22 @@ function titleToName(value) {
|
|
|
3567
3627
|
/**
|
|
3568
3628
|
* The built-in `fetch' function with a lightweight error handling wrapper as default fetch function used in Promptbook scrapers
|
|
3569
3629
|
*
|
|
3570
|
-
* @
|
|
3630
|
+
* @public exported from `@promptbook/core`
|
|
3571
3631
|
*/
|
|
3572
|
-
const
|
|
3632
|
+
const promptbookFetch = async (urlOrRequest, init) => {
|
|
3573
3633
|
try {
|
|
3574
|
-
return await fetch(
|
|
3634
|
+
return await fetch(urlOrRequest, init);
|
|
3575
3635
|
}
|
|
3576
3636
|
catch (error) {
|
|
3577
|
-
|
|
3578
|
-
|
|
3637
|
+
assertsError(error);
|
|
3638
|
+
let url;
|
|
3639
|
+
if (typeof urlOrRequest === 'string') {
|
|
3640
|
+
url = urlOrRequest;
|
|
3641
|
+
}
|
|
3642
|
+
else if (urlOrRequest instanceof Request) {
|
|
3643
|
+
url = urlOrRequest.url;
|
|
3579
3644
|
}
|
|
3580
|
-
throw new
|
|
3645
|
+
throw new PromptbookFetchError(spaceTrim((block) => `
|
|
3581
3646
|
Can not fetch "${url}"
|
|
3582
3647
|
|
|
3583
3648
|
Fetch error:
|
|
@@ -3598,7 +3663,7 @@ const scraperFetch = async (url, init) => {
|
|
|
3598
3663
|
async function makeKnowledgeSourceHandler(knowledgeSource, tools, options) {
|
|
3599
3664
|
// console.log('!! makeKnowledgeSourceHandler', knowledgeSource);
|
|
3600
3665
|
var _a;
|
|
3601
|
-
const { fetch =
|
|
3666
|
+
const { fetch = promptbookFetch } = tools;
|
|
3602
3667
|
const { knowledgeSourceContent } = knowledgeSource;
|
|
3603
3668
|
let { name } = knowledgeSource;
|
|
3604
3669
|
const { rootDirname = null,
|
|
@@ -3668,7 +3733,7 @@ async function makeKnowledgeSourceHandler(knowledgeSource, tools, options) {
|
|
|
3668
3733
|
const fileExtension = getFileExtension(filename);
|
|
3669
3734
|
const mimeType = extensionToMimeType(fileExtension || '');
|
|
3670
3735
|
if (!(await isFileExisting(filename, tools.fs))) {
|
|
3671
|
-
throw new NotFoundError(spaceTrim
|
|
3736
|
+
throw new NotFoundError(spaceTrim((block) => `
|
|
3672
3737
|
Can not make source handler for file which does not exist:
|
|
3673
3738
|
|
|
3674
3739
|
File:
|
|
@@ -3755,7 +3820,7 @@ async function prepareKnowledgePieces(knowledgeSources, tools, options) {
|
|
|
3755
3820
|
// <- TODO: [🪓] Here should be no need for spreading new array, just `partialPieces = partialPiecesUnchecked`
|
|
3756
3821
|
break;
|
|
3757
3822
|
}
|
|
3758
|
-
console.warn(spaceTrim
|
|
3823
|
+
console.warn(spaceTrim((block) => `
|
|
3759
3824
|
Cannot scrape knowledge from source despite the scraper \`${scraper.metadata.className}\` supports the mime type "${sourceHandler.mimeType}".
|
|
3760
3825
|
|
|
3761
3826
|
The source:
|
|
@@ -3771,7 +3836,7 @@ async function prepareKnowledgePieces(knowledgeSources, tools, options) {
|
|
|
3771
3836
|
// <- TODO: [🏮] Some standard way how to transform errors into warnings and how to handle non-critical fails during the tasks
|
|
3772
3837
|
}
|
|
3773
3838
|
if (partialPieces === null) {
|
|
3774
|
-
throw new KnowledgeScrapeError(spaceTrim
|
|
3839
|
+
throw new KnowledgeScrapeError(spaceTrim((block) => `
|
|
3775
3840
|
Cannot scrape knowledge
|
|
3776
3841
|
|
|
3777
3842
|
The source:
|
|
@@ -3800,9 +3865,7 @@ async function prepareKnowledgePieces(knowledgeSources, tools, options) {
|
|
|
3800
3865
|
knowledgePreparedUnflatten[index] = pieces;
|
|
3801
3866
|
}
|
|
3802
3867
|
catch (error) {
|
|
3803
|
-
|
|
3804
|
-
throw error;
|
|
3805
|
-
}
|
|
3868
|
+
assertsError(error);
|
|
3806
3869
|
console.warn(error);
|
|
3807
3870
|
// <- TODO: [🏮] Some standard way how to transform errors into warnings and how to handle non-critical fails during the tasks
|
|
3808
3871
|
}
|
|
@@ -3849,7 +3912,7 @@ async function prepareTasks(pipeline, tools, options) {
|
|
|
3849
3912
|
if (task.taskType === 'PROMPT_TASK' &&
|
|
3850
3913
|
knowledgePiecesCount > 0 &&
|
|
3851
3914
|
!dependentParameterNames.includes('knowledge')) {
|
|
3852
|
-
preparedContent = spaceTrim(`
|
|
3915
|
+
preparedContent = spaceTrim$1(`
|
|
3853
3916
|
{content}
|
|
3854
3917
|
|
|
3855
3918
|
## Knowledge
|
|
@@ -4094,13 +4157,19 @@ function valueToString(value) {
|
|
|
4094
4157
|
return value.toISOString();
|
|
4095
4158
|
}
|
|
4096
4159
|
else {
|
|
4097
|
-
|
|
4160
|
+
try {
|
|
4161
|
+
return JSON.stringify(value);
|
|
4162
|
+
}
|
|
4163
|
+
catch (error) {
|
|
4164
|
+
if (error instanceof TypeError && error.message.includes('circular structure')) {
|
|
4165
|
+
return VALUE_STRINGS.circular;
|
|
4166
|
+
}
|
|
4167
|
+
throw error;
|
|
4168
|
+
}
|
|
4098
4169
|
}
|
|
4099
4170
|
}
|
|
4100
4171
|
catch (error) {
|
|
4101
|
-
|
|
4102
|
-
throw error;
|
|
4103
|
-
}
|
|
4172
|
+
assertsError(error);
|
|
4104
4173
|
console.error(error);
|
|
4105
4174
|
return VALUE_STRINGS.unserializable;
|
|
4106
4175
|
}
|
|
@@ -4157,10 +4226,8 @@ function extractVariablesFromJavascript(script) {
|
|
|
4157
4226
|
}
|
|
4158
4227
|
}
|
|
4159
4228
|
catch (error) {
|
|
4160
|
-
|
|
4161
|
-
|
|
4162
|
-
}
|
|
4163
|
-
throw new ParseError(spaceTrim((block) => `
|
|
4229
|
+
assertsError(error);
|
|
4230
|
+
throw new ParseError(spaceTrim$1((block) => `
|
|
4164
4231
|
Can not extract variables from the script
|
|
4165
4232
|
${block(error.stack || error.message)}
|
|
4166
4233
|
|
|
@@ -4278,6 +4345,28 @@ const MANDATORY_CSV_SETTINGS = Object.freeze({
|
|
|
4278
4345
|
// encoding: 'utf-8',
|
|
4279
4346
|
});
|
|
4280
4347
|
|
|
4348
|
+
/**
|
|
4349
|
+
* Function to check if a string is valid CSV
|
|
4350
|
+
*
|
|
4351
|
+
* @param value The string to check
|
|
4352
|
+
* @returns True if the string is a valid CSV string, false otherwise
|
|
4353
|
+
*
|
|
4354
|
+
* @public exported from `@promptbook/utils`
|
|
4355
|
+
*/
|
|
4356
|
+
function isValidCsvString(value) {
|
|
4357
|
+
try {
|
|
4358
|
+
// A simple check for CSV format: at least one comma and no invalid characters
|
|
4359
|
+
if (value.includes(',') && /^[\w\s,"']+$/.test(value)) {
|
|
4360
|
+
return true;
|
|
4361
|
+
}
|
|
4362
|
+
return false;
|
|
4363
|
+
}
|
|
4364
|
+
catch (error) {
|
|
4365
|
+
assertsError(error);
|
|
4366
|
+
return false;
|
|
4367
|
+
}
|
|
4368
|
+
}
|
|
4369
|
+
|
|
4281
4370
|
/**
|
|
4282
4371
|
* Definition for CSV spreadsheet
|
|
4283
4372
|
*
|
|
@@ -4288,7 +4377,7 @@ const CsvFormatDefinition = {
|
|
|
4288
4377
|
formatName: 'CSV',
|
|
4289
4378
|
aliases: ['SPREADSHEET', 'TABLE'],
|
|
4290
4379
|
isValid(value, settings, schema) {
|
|
4291
|
-
return
|
|
4380
|
+
return isValidCsvString(value);
|
|
4292
4381
|
},
|
|
4293
4382
|
canBeValid(partialValue, settings, schema) {
|
|
4294
4383
|
return true;
|
|
@@ -4303,7 +4392,7 @@ const CsvFormatDefinition = {
|
|
|
4303
4392
|
// TODO: [👨🏾🤝👨🏼] DRY csv parsing
|
|
4304
4393
|
const csv = parse(value, { ...settings, ...MANDATORY_CSV_SETTINGS });
|
|
4305
4394
|
if (csv.errors.length !== 0) {
|
|
4306
|
-
throw new CsvFormatError(spaceTrim
|
|
4395
|
+
throw new CsvFormatError(spaceTrim((block) => `
|
|
4307
4396
|
CSV parsing error
|
|
4308
4397
|
|
|
4309
4398
|
Error(s) from CSV parsing:
|
|
@@ -4334,7 +4423,7 @@ const CsvFormatDefinition = {
|
|
|
4334
4423
|
// TODO: [👨🏾🤝👨🏼] DRY csv parsing
|
|
4335
4424
|
const csv = parse(value, { ...settings, ...MANDATORY_CSV_SETTINGS });
|
|
4336
4425
|
if (csv.errors.length !== 0) {
|
|
4337
|
-
throw new CsvFormatError(spaceTrim
|
|
4426
|
+
throw new CsvFormatError(spaceTrim((block) => `
|
|
4338
4427
|
CSV parsing error
|
|
4339
4428
|
|
|
4340
4429
|
Error(s) from CSV parsing:
|
|
@@ -4442,6 +4531,30 @@ const TextFormatDefinition = {
|
|
|
4442
4531
|
* TODO: [🏢] Allow to expect something inside each item of list and other formats
|
|
4443
4532
|
*/
|
|
4444
4533
|
|
|
4534
|
+
/**
|
|
4535
|
+
* Function to check if a string is valid XML
|
|
4536
|
+
*
|
|
4537
|
+
* @param value
|
|
4538
|
+
* @returns True if the string is a valid XML string, false otherwise
|
|
4539
|
+
*
|
|
4540
|
+
* @public exported from `@promptbook/utils`
|
|
4541
|
+
*/
|
|
4542
|
+
function isValidXmlString(value) {
|
|
4543
|
+
try {
|
|
4544
|
+
const parser = new DOMParser();
|
|
4545
|
+
const parsedDocument = parser.parseFromString(value, 'application/xml');
|
|
4546
|
+
const parserError = parsedDocument.getElementsByTagName('parsererror');
|
|
4547
|
+
if (parserError.length > 0) {
|
|
4548
|
+
return false;
|
|
4549
|
+
}
|
|
4550
|
+
return true;
|
|
4551
|
+
}
|
|
4552
|
+
catch (error) {
|
|
4553
|
+
assertsError(error);
|
|
4554
|
+
return false;
|
|
4555
|
+
}
|
|
4556
|
+
}
|
|
4557
|
+
|
|
4445
4558
|
/**
|
|
4446
4559
|
* Definition for XML format
|
|
4447
4560
|
*
|
|
@@ -4451,7 +4564,7 @@ const XmlFormatDefinition = {
|
|
|
4451
4564
|
formatName: 'XML',
|
|
4452
4565
|
mimeType: 'application/xml',
|
|
4453
4566
|
isValid(value, settings, schema) {
|
|
4454
|
-
return
|
|
4567
|
+
return isValidXmlString(value);
|
|
4455
4568
|
},
|
|
4456
4569
|
canBeValid(partialValue, settings, schema) {
|
|
4457
4570
|
return true;
|
|
@@ -4524,7 +4637,7 @@ function mapAvailableToExpectedParameters(options) {
|
|
|
4524
4637
|
}
|
|
4525
4638
|
// Phase 2️⃣: Non-matching mapping
|
|
4526
4639
|
if (expectedParameterNames.size !== availableParametersNames.size) {
|
|
4527
|
-
throw new PipelineExecutionError(spaceTrim
|
|
4640
|
+
throw new PipelineExecutionError(spaceTrim((block) => `
|
|
4528
4641
|
Can not map available parameters to expected parameters
|
|
4529
4642
|
|
|
4530
4643
|
Mapped parameters:
|
|
@@ -4926,7 +5039,7 @@ async function executeAttempts(options) {
|
|
|
4926
5039
|
const jokerParameterName = jokerParameterNames[jokerParameterNames.length + attempt];
|
|
4927
5040
|
// TODO: [🧠][🍭] JOKERS, EXPECTATIONS, POSTPROCESSING and FOREACH
|
|
4928
5041
|
if (isJokerAttempt && !jokerParameterName) {
|
|
4929
|
-
throw new UnexpectedError(spaceTrim((block) => `
|
|
5042
|
+
throw new UnexpectedError(spaceTrim$1((block) => `
|
|
4930
5043
|
Joker not found in attempt ${attempt}
|
|
4931
5044
|
|
|
4932
5045
|
${block(pipelineIdentification)}
|
|
@@ -4937,7 +5050,7 @@ async function executeAttempts(options) {
|
|
|
4937
5050
|
$ongoingTaskResult.$expectError = null;
|
|
4938
5051
|
if (isJokerAttempt) {
|
|
4939
5052
|
if (parameters[jokerParameterName] === undefined) {
|
|
4940
|
-
throw new PipelineExecutionError(spaceTrim((block) => `
|
|
5053
|
+
throw new PipelineExecutionError(spaceTrim$1((block) => `
|
|
4941
5054
|
Joker parameter {${jokerParameterName}} not defined
|
|
4942
5055
|
|
|
4943
5056
|
${block(pipelineIdentification)}
|
|
@@ -4995,7 +5108,7 @@ async function executeAttempts(options) {
|
|
|
4995
5108
|
$ongoingTaskResult.$resultString = $ongoingTaskResult.$completionResult.content;
|
|
4996
5109
|
break variant;
|
|
4997
5110
|
case 'EMBEDDING':
|
|
4998
|
-
throw new PipelineExecutionError(spaceTrim((block) => `
|
|
5111
|
+
throw new PipelineExecutionError(spaceTrim$1((block) => `
|
|
4999
5112
|
Embedding model can not be used in pipeline
|
|
5000
5113
|
|
|
5001
5114
|
This should be catched during parsing
|
|
@@ -5006,7 +5119,7 @@ async function executeAttempts(options) {
|
|
|
5006
5119
|
break variant;
|
|
5007
5120
|
// <- case [🤖]:
|
|
5008
5121
|
default:
|
|
5009
|
-
throw new PipelineExecutionError(spaceTrim((block) => `
|
|
5122
|
+
throw new PipelineExecutionError(spaceTrim$1((block) => `
|
|
5010
5123
|
Unknown model variant "${task.modelRequirements.modelVariant}"
|
|
5011
5124
|
|
|
5012
5125
|
${block(pipelineIdentification)}
|
|
@@ -5017,14 +5130,14 @@ async function executeAttempts(options) {
|
|
|
5017
5130
|
break;
|
|
5018
5131
|
case 'SCRIPT_TASK':
|
|
5019
5132
|
if (arrayableToArray(tools.script).length === 0) {
|
|
5020
|
-
throw new PipelineExecutionError(spaceTrim((block) => `
|
|
5133
|
+
throw new PipelineExecutionError(spaceTrim$1((block) => `
|
|
5021
5134
|
No script execution tools are available
|
|
5022
5135
|
|
|
5023
5136
|
${block(pipelineIdentification)}
|
|
5024
5137
|
`));
|
|
5025
5138
|
}
|
|
5026
5139
|
if (!task.contentLanguage) {
|
|
5027
|
-
throw new PipelineExecutionError(spaceTrim((block) => `
|
|
5140
|
+
throw new PipelineExecutionError(spaceTrim$1((block) => `
|
|
5028
5141
|
Script language is not defined for SCRIPT TASK "${task.name}"
|
|
5029
5142
|
|
|
5030
5143
|
${block(pipelineIdentification)}
|
|
@@ -5041,9 +5154,7 @@ async function executeAttempts(options) {
|
|
|
5041
5154
|
break scripts;
|
|
5042
5155
|
}
|
|
5043
5156
|
catch (error) {
|
|
5044
|
-
|
|
5045
|
-
throw error;
|
|
5046
|
-
}
|
|
5157
|
+
assertsError(error);
|
|
5047
5158
|
if (error instanceof UnexpectedError) {
|
|
5048
5159
|
throw error;
|
|
5049
5160
|
}
|
|
@@ -5057,7 +5168,7 @@ async function executeAttempts(options) {
|
|
|
5057
5168
|
throw $ongoingTaskResult.$scriptPipelineExecutionErrors[0];
|
|
5058
5169
|
}
|
|
5059
5170
|
else {
|
|
5060
|
-
throw new PipelineExecutionError(spaceTrim((block) => `
|
|
5171
|
+
throw new PipelineExecutionError(spaceTrim$1((block) => `
|
|
5061
5172
|
Script execution failed ${$ongoingTaskResult.$scriptPipelineExecutionErrors.length}x
|
|
5062
5173
|
|
|
5063
5174
|
${block(pipelineIdentification)}
|
|
@@ -5071,7 +5182,7 @@ async function executeAttempts(options) {
|
|
|
5071
5182
|
break taskType;
|
|
5072
5183
|
case 'DIALOG_TASK':
|
|
5073
5184
|
if (tools.userInterface === undefined) {
|
|
5074
|
-
throw new PipelineExecutionError(spaceTrim((block) => `
|
|
5185
|
+
throw new PipelineExecutionError(spaceTrim$1((block) => `
|
|
5075
5186
|
User interface tools are not available
|
|
5076
5187
|
|
|
5077
5188
|
${block(pipelineIdentification)}
|
|
@@ -5089,7 +5200,7 @@ async function executeAttempts(options) {
|
|
|
5089
5200
|
break taskType;
|
|
5090
5201
|
// <- case: [🅱]
|
|
5091
5202
|
default:
|
|
5092
|
-
throw new PipelineExecutionError(spaceTrim((block) => `
|
|
5203
|
+
throw new PipelineExecutionError(spaceTrim$1((block) => `
|
|
5093
5204
|
Unknown execution type "${task.taskType}"
|
|
5094
5205
|
|
|
5095
5206
|
${block(pipelineIdentification)}
|
|
@@ -5113,9 +5224,7 @@ async function executeAttempts(options) {
|
|
|
5113
5224
|
break scripts;
|
|
5114
5225
|
}
|
|
5115
5226
|
catch (error) {
|
|
5116
|
-
|
|
5117
|
-
throw error;
|
|
5118
|
-
}
|
|
5227
|
+
assertsError(error);
|
|
5119
5228
|
if (error instanceof UnexpectedError) {
|
|
5120
5229
|
throw error;
|
|
5121
5230
|
}
|
|
@@ -5138,7 +5247,7 @@ async function executeAttempts(options) {
|
|
|
5138
5247
|
}
|
|
5139
5248
|
catch (error) {
|
|
5140
5249
|
keepUnused(error);
|
|
5141
|
-
throw new ExpectError(spaceTrim((block) => `
|
|
5250
|
+
throw new ExpectError(spaceTrim$1((block) => `
|
|
5142
5251
|
Expected valid JSON string
|
|
5143
5252
|
|
|
5144
5253
|
${block(
|
|
@@ -5148,7 +5257,7 @@ async function executeAttempts(options) {
|
|
|
5148
5257
|
}
|
|
5149
5258
|
}
|
|
5150
5259
|
else {
|
|
5151
|
-
throw new UnexpectedError(spaceTrim((block) => `
|
|
5260
|
+
throw new UnexpectedError(spaceTrim$1((block) => `
|
|
5152
5261
|
Unknown format "${task.format}"
|
|
5153
5262
|
|
|
5154
5263
|
${block(pipelineIdentification)}
|
|
@@ -5188,7 +5297,7 @@ async function executeAttempts(options) {
|
|
|
5188
5297
|
}
|
|
5189
5298
|
}
|
|
5190
5299
|
if ($ongoingTaskResult.$expectError !== null && attempt === maxAttempts - 1) {
|
|
5191
|
-
throw new PipelineExecutionError(spaceTrim((block) => {
|
|
5300
|
+
throw new PipelineExecutionError(spaceTrim$1((block) => {
|
|
5192
5301
|
var _a, _b, _c;
|
|
5193
5302
|
return `
|
|
5194
5303
|
LLM execution failed ${maxExecutionAttempts}x
|
|
@@ -5211,7 +5320,7 @@ async function executeAttempts(options) {
|
|
|
5211
5320
|
Last result:
|
|
5212
5321
|
${block($ongoingTaskResult.$resultString === null
|
|
5213
5322
|
? 'null'
|
|
5214
|
-
: spaceTrim($ongoingTaskResult.$resultString)
|
|
5323
|
+
: spaceTrim$1($ongoingTaskResult.$resultString)
|
|
5215
5324
|
.split('\n')
|
|
5216
5325
|
.map((line) => `> ${line}`)
|
|
5217
5326
|
.join('\n'))}
|
|
@@ -5221,7 +5330,7 @@ async function executeAttempts(options) {
|
|
|
5221
5330
|
}
|
|
5222
5331
|
}
|
|
5223
5332
|
if ($ongoingTaskResult.$resultString === null) {
|
|
5224
|
-
throw new UnexpectedError(spaceTrim((block) => `
|
|
5333
|
+
throw new UnexpectedError(spaceTrim$1((block) => `
|
|
5225
5334
|
Something went wrong and prompt result is null
|
|
5226
5335
|
|
|
5227
5336
|
${block(pipelineIdentification)}
|
|
@@ -5244,7 +5353,7 @@ async function executeFormatSubvalues(options) {
|
|
|
5244
5353
|
return /* not await */ executeAttempts(options);
|
|
5245
5354
|
}
|
|
5246
5355
|
if (jokerParameterNames.length !== 0) {
|
|
5247
|
-
throw new UnexpectedError(spaceTrim
|
|
5356
|
+
throw new UnexpectedError(spaceTrim((block) => `
|
|
5248
5357
|
JOKER parameters are not supported together with FOREACH command
|
|
5249
5358
|
|
|
5250
5359
|
[🧞♀️] This should be prevented in \`validatePipeline\`
|
|
@@ -5257,7 +5366,7 @@ async function executeFormatSubvalues(options) {
|
|
|
5257
5366
|
if (formatDefinition === undefined) {
|
|
5258
5367
|
throw new UnexpectedError(
|
|
5259
5368
|
// <- TODO: [🧠][🧐] Should be formats fixed per promptbook version or behave as plugins (=> change UnexpectedError)
|
|
5260
|
-
spaceTrim
|
|
5369
|
+
spaceTrim((block) => `
|
|
5261
5370
|
Unsupported format "${task.foreach.formatName}"
|
|
5262
5371
|
|
|
5263
5372
|
Available formats:
|
|
@@ -5274,7 +5383,7 @@ async function executeFormatSubvalues(options) {
|
|
|
5274
5383
|
if (subvalueDefinition === undefined) {
|
|
5275
5384
|
throw new UnexpectedError(
|
|
5276
5385
|
// <- TODO: [🧠][🧐] Should be formats fixed per promptbook version or behave as plugins (=> change UnexpectedError)
|
|
5277
|
-
spaceTrim
|
|
5386
|
+
spaceTrim((block) => `
|
|
5278
5387
|
Unsupported subformat name "${task.foreach.subformatName}" for format "${task.foreach.formatName}"
|
|
5279
5388
|
|
|
5280
5389
|
Available subformat names for format "${formatDefinition.formatName}":
|
|
@@ -5307,7 +5416,7 @@ async function executeFormatSubvalues(options) {
|
|
|
5307
5416
|
if (!(error instanceof PipelineExecutionError)) {
|
|
5308
5417
|
throw error;
|
|
5309
5418
|
}
|
|
5310
|
-
throw new PipelineExecutionError(spaceTrim
|
|
5419
|
+
throw new PipelineExecutionError(spaceTrim((block) => `
|
|
5311
5420
|
${error.message}
|
|
5312
5421
|
|
|
5313
5422
|
This is error in FOREACH command
|
|
@@ -5327,7 +5436,7 @@ async function executeFormatSubvalues(options) {
|
|
|
5327
5436
|
...options,
|
|
5328
5437
|
priority: priority + index,
|
|
5329
5438
|
parameters: allSubparameters,
|
|
5330
|
-
pipelineIdentification: spaceTrim
|
|
5439
|
+
pipelineIdentification: spaceTrim((block) => `
|
|
5331
5440
|
${block(pipelineIdentification)}
|
|
5332
5441
|
Subparameter index: ${index}
|
|
5333
5442
|
`),
|
|
@@ -5389,7 +5498,7 @@ async function getReservedParametersForTask(options) {
|
|
|
5389
5498
|
// Note: Doublecheck that ALL reserved parameters are defined:
|
|
5390
5499
|
for (const parameterName of RESERVED_PARAMETER_NAMES) {
|
|
5391
5500
|
if (reservedParameters[parameterName] === undefined) {
|
|
5392
|
-
throw new UnexpectedError(spaceTrim((block) => `
|
|
5501
|
+
throw new UnexpectedError(spaceTrim$1((block) => `
|
|
5393
5502
|
Reserved parameter {${parameterName}} is not defined
|
|
5394
5503
|
|
|
5395
5504
|
${block(pipelineIdentification)}
|
|
@@ -5417,7 +5526,7 @@ async function executeTask(options) {
|
|
|
5417
5526
|
const dependentParameterNames = new Set(currentTask.dependentParameterNames);
|
|
5418
5527
|
// TODO: [👩🏾🤝👩🏻] Use here `mapAvailableToExpectedParameters`
|
|
5419
5528
|
if (union(difference(usedParameterNames, dependentParameterNames), difference(dependentParameterNames, usedParameterNames)).size !== 0) {
|
|
5420
|
-
throw new UnexpectedError(spaceTrim((block) => `
|
|
5529
|
+
throw new UnexpectedError(spaceTrim$1((block) => `
|
|
5421
5530
|
Dependent parameters are not consistent with used parameters:
|
|
5422
5531
|
|
|
5423
5532
|
Dependent parameters:
|
|
@@ -5457,7 +5566,7 @@ async function executeTask(options) {
|
|
|
5457
5566
|
else if (!definedParameterNames.has(parameterName) && usedParameterNames.has(parameterName)) {
|
|
5458
5567
|
// Houston, we have a problem
|
|
5459
5568
|
// Note: Checking part is also done in `validatePipeline`, but it’s good to doublecheck
|
|
5460
|
-
throw new UnexpectedError(spaceTrim((block) => `
|
|
5569
|
+
throw new UnexpectedError(spaceTrim$1((block) => `
|
|
5461
5570
|
Parameter \`{${parameterName}}\` is NOT defined
|
|
5462
5571
|
BUT used in task "${currentTask.title || currentTask.name}"
|
|
5463
5572
|
|
|
@@ -5523,7 +5632,7 @@ function filterJustOutputParameters(options) {
|
|
|
5523
5632
|
for (const parameter of preparedPipeline.parameters.filter(({ isOutput }) => isOutput)) {
|
|
5524
5633
|
if (parametersToPass[parameter.name] === undefined) {
|
|
5525
5634
|
// [4]
|
|
5526
|
-
$warnings.push(new PipelineExecutionError(spaceTrim((block) => `
|
|
5635
|
+
$warnings.push(new PipelineExecutionError(spaceTrim$1((block) => `
|
|
5527
5636
|
Parameter \`{${parameter.name}}\` should be an output parameter, but it was not generated during pipeline execution
|
|
5528
5637
|
|
|
5529
5638
|
${block(pipelineIdentification)}
|
|
@@ -5598,7 +5707,7 @@ async function executePipeline(options) {
|
|
|
5598
5707
|
for (const parameterName of Object.keys(inputParameters)) {
|
|
5599
5708
|
const parameter = preparedPipeline.parameters.find(({ name }) => name === parameterName);
|
|
5600
5709
|
if (parameter === undefined) {
|
|
5601
|
-
warnings.push(new PipelineExecutionError(spaceTrim((block) => `
|
|
5710
|
+
warnings.push(new PipelineExecutionError(spaceTrim$1((block) => `
|
|
5602
5711
|
Extra parameter {${parameterName}} is being passed which is not part of the pipeline.
|
|
5603
5712
|
|
|
5604
5713
|
${block(pipelineIdentification)}
|
|
@@ -5613,7 +5722,7 @@ async function executePipeline(options) {
|
|
|
5613
5722
|
// TODO: [🧠] This should be also non-critical error
|
|
5614
5723
|
return exportJson({
|
|
5615
5724
|
name: 'pipelineExecutorResult',
|
|
5616
|
-
message: spaceTrim((block) => `
|
|
5725
|
+
message: spaceTrim$1((block) => `
|
|
5617
5726
|
Unuccessful PipelineExecutorResult (with extra parameter {${parameter.name}}) PipelineExecutorResult
|
|
5618
5727
|
|
|
5619
5728
|
${block(pipelineIdentification)}
|
|
@@ -5622,7 +5731,7 @@ async function executePipeline(options) {
|
|
|
5622
5731
|
value: {
|
|
5623
5732
|
isSuccessful: false,
|
|
5624
5733
|
errors: [
|
|
5625
|
-
new PipelineExecutionError(spaceTrim((block) => `
|
|
5734
|
+
new PipelineExecutionError(spaceTrim$1((block) => `
|
|
5626
5735
|
Parameter \`{${parameter.name}}\` is passed as input parameter but it is not input
|
|
5627
5736
|
|
|
5628
5737
|
${block(pipelineIdentification)}
|
|
@@ -5649,7 +5758,7 @@ async function executePipeline(options) {
|
|
|
5649
5758
|
while (unresovedTasks.length > 0) {
|
|
5650
5759
|
if (loopLimit-- < 0) {
|
|
5651
5760
|
// Note: Really UnexpectedError not LimitReachedError - this should be catched during validatePipeline
|
|
5652
|
-
throw new UnexpectedError(spaceTrim((block) => `
|
|
5761
|
+
throw new UnexpectedError(spaceTrim$1((block) => `
|
|
5653
5762
|
Loop limit reached during resolving parameters pipeline execution
|
|
5654
5763
|
|
|
5655
5764
|
${block(pipelineIdentification)}
|
|
@@ -5659,7 +5768,7 @@ async function executePipeline(options) {
|
|
|
5659
5768
|
if (!currentTask && resolving.length === 0) {
|
|
5660
5769
|
throw new UnexpectedError(
|
|
5661
5770
|
// TODO: [🐎] DRY
|
|
5662
|
-
spaceTrim((block) => `
|
|
5771
|
+
spaceTrim$1((block) => `
|
|
5663
5772
|
Can not resolve some parameters:
|
|
5664
5773
|
|
|
5665
5774
|
${block(pipelineIdentification)}
|
|
@@ -5699,7 +5808,7 @@ async function executePipeline(options) {
|
|
|
5699
5808
|
tools,
|
|
5700
5809
|
onProgress(newOngoingResult) {
|
|
5701
5810
|
if (isReturned) {
|
|
5702
|
-
throw new UnexpectedError(spaceTrim((block) => `
|
|
5811
|
+
throw new UnexpectedError(spaceTrim$1((block) => `
|
|
5703
5812
|
Can not call \`onProgress\` after pipeline execution is finished
|
|
5704
5813
|
|
|
5705
5814
|
${block(pipelineIdentification)}
|
|
@@ -5715,7 +5824,7 @@ async function executePipeline(options) {
|
|
|
5715
5824
|
}
|
|
5716
5825
|
},
|
|
5717
5826
|
$executionReport: executionReport,
|
|
5718
|
-
pipelineIdentification: spaceTrim((block) => `
|
|
5827
|
+
pipelineIdentification: spaceTrim$1((block) => `
|
|
5719
5828
|
${block(pipelineIdentification)}
|
|
5720
5829
|
Task name: ${currentTask.name}
|
|
5721
5830
|
Task title: ${currentTask.title}
|
|
@@ -5736,9 +5845,7 @@ async function executePipeline(options) {
|
|
|
5736
5845
|
await Promise.all(resolving);
|
|
5737
5846
|
}
|
|
5738
5847
|
catch (error /* <- Note: [3] */) {
|
|
5739
|
-
|
|
5740
|
-
throw error;
|
|
5741
|
-
}
|
|
5848
|
+
assertsError(error);
|
|
5742
5849
|
// Note: No need to rethrow UnexpectedError
|
|
5743
5850
|
// if (error instanceof UnexpectedError) {
|
|
5744
5851
|
// Note: Count usage, [🧠] Maybe put to separate function executionReportJsonToUsage + DRY [🤹♂️]
|
|
@@ -5826,7 +5933,7 @@ function createPipelineExecutor(options) {
|
|
|
5826
5933
|
preparedPipeline = pipeline;
|
|
5827
5934
|
}
|
|
5828
5935
|
else if (isNotPreparedWarningSupressed !== true) {
|
|
5829
|
-
console.warn(spaceTrim((block) => `
|
|
5936
|
+
console.warn(spaceTrim$1((block) => `
|
|
5830
5937
|
Pipeline is not prepared
|
|
5831
5938
|
|
|
5832
5939
|
${block(pipelineIdentification)}
|
|
@@ -5850,7 +5957,7 @@ function createPipelineExecutor(options) {
|
|
|
5850
5957
|
inputParameters,
|
|
5851
5958
|
tools,
|
|
5852
5959
|
onProgress,
|
|
5853
|
-
pipelineIdentification: spaceTrim((block) => `
|
|
5960
|
+
pipelineIdentification: spaceTrim$1((block) => `
|
|
5854
5961
|
${block(pipelineIdentification)}
|
|
5855
5962
|
${runCount === 1 ? '' : `Run #${runCount}`}
|
|
5856
5963
|
`),
|
|
@@ -5948,13 +6055,13 @@ function $registeredLlmToolsMessage() {
|
|
|
5948
6055
|
});
|
|
5949
6056
|
const usedEnvMessage = `Unknown \`.env\` file` ;
|
|
5950
6057
|
if (metadata.length === 0) {
|
|
5951
|
-
return spaceTrim
|
|
6058
|
+
return spaceTrim((block) => `
|
|
5952
6059
|
No LLM providers are available.
|
|
5953
6060
|
|
|
5954
6061
|
${block(usedEnvMessage)}
|
|
5955
6062
|
`);
|
|
5956
6063
|
}
|
|
5957
|
-
return spaceTrim
|
|
6064
|
+
return spaceTrim((block) => `
|
|
5958
6065
|
|
|
5959
6066
|
${block(usedEnvMessage)}
|
|
5960
6067
|
|
|
@@ -6000,7 +6107,7 @@ function $registeredLlmToolsMessage() {
|
|
|
6000
6107
|
morePieces.push(`Not configured`); // <- Note: Can not be configured via environment variables
|
|
6001
6108
|
}
|
|
6002
6109
|
}
|
|
6003
|
-
let providerMessage = spaceTrim
|
|
6110
|
+
let providerMessage = spaceTrim(`
|
|
6004
6111
|
${i + 1}) **${title}** \`${className}\` from \`${packageName}\`
|
|
6005
6112
|
${morePieces.join('; ')}
|
|
6006
6113
|
`);
|
|
@@ -6040,7 +6147,7 @@ function createLlmToolsFromConfiguration(configuration, options = {}) {
|
|
|
6040
6147
|
.list()
|
|
6041
6148
|
.find(({ packageName, className }) => llmConfiguration.packageName === packageName && llmConfiguration.className === className);
|
|
6042
6149
|
if (registeredItem === undefined) {
|
|
6043
|
-
throw new Error(spaceTrim
|
|
6150
|
+
throw new Error(spaceTrim((block) => `
|
|
6044
6151
|
There is no constructor for LLM provider \`${llmConfiguration.className}\` from \`${llmConfiguration.packageName}\`
|
|
6045
6152
|
|
|
6046
6153
|
You have probably forgotten install and import the provider package.
|
|
@@ -6324,13 +6431,13 @@ function removeQuotes(text) {
|
|
|
6324
6431
|
* @public exported from `@promptbook/utils`
|
|
6325
6432
|
*/
|
|
6326
6433
|
function trimCodeBlock(value) {
|
|
6327
|
-
value = spaceTrim(value);
|
|
6434
|
+
value = spaceTrim$1(value);
|
|
6328
6435
|
if (!/^```[a-z]*(.*)```$/is.test(value)) {
|
|
6329
6436
|
return value;
|
|
6330
6437
|
}
|
|
6331
6438
|
value = value.replace(/^```[a-z]*/i, '');
|
|
6332
6439
|
value = value.replace(/```$/i, '');
|
|
6333
|
-
value = spaceTrim(value);
|
|
6440
|
+
value = spaceTrim$1(value);
|
|
6334
6441
|
return value;
|
|
6335
6442
|
}
|
|
6336
6443
|
|
|
@@ -6343,9 +6450,9 @@ function trimCodeBlock(value) {
|
|
|
6343
6450
|
* @public exported from `@promptbook/utils`
|
|
6344
6451
|
*/
|
|
6345
6452
|
function trimEndOfCodeBlock(value) {
|
|
6346
|
-
value = spaceTrim(value);
|
|
6453
|
+
value = spaceTrim$1(value);
|
|
6347
6454
|
value = value.replace(/```$/g, '');
|
|
6348
|
-
value = spaceTrim(value);
|
|
6455
|
+
value = spaceTrim$1(value);
|
|
6349
6456
|
return value;
|
|
6350
6457
|
}
|
|
6351
6458
|
|
|
@@ -6367,7 +6474,7 @@ function unwrapResult(text, options) {
|
|
|
6367
6474
|
let trimmedText = text;
|
|
6368
6475
|
// Remove leading and trailing spaces and newlines
|
|
6369
6476
|
if (isTrimmed) {
|
|
6370
|
-
trimmedText = spaceTrim(trimmedText);
|
|
6477
|
+
trimmedText = spaceTrim$1(trimmedText);
|
|
6371
6478
|
}
|
|
6372
6479
|
let processedText = trimmedText;
|
|
6373
6480
|
if (isIntroduceSentenceRemoved) {
|
|
@@ -6376,7 +6483,7 @@ function unwrapResult(text, options) {
|
|
|
6376
6483
|
// Remove the introduce sentence and quotes by replacing it with an empty string
|
|
6377
6484
|
processedText = processedText.replace(introduceSentenceRegex, '');
|
|
6378
6485
|
}
|
|
6379
|
-
processedText = spaceTrim(processedText);
|
|
6486
|
+
processedText = spaceTrim$1(processedText);
|
|
6380
6487
|
}
|
|
6381
6488
|
if (processedText.length < 3) {
|
|
6382
6489
|
return trimmedText;
|
|
@@ -6439,7 +6546,7 @@ function unwrapResult(text, options) {
|
|
|
6439
6546
|
function extractOneBlockFromMarkdown(markdown) {
|
|
6440
6547
|
const codeBlocks = extractAllBlocksFromMarkdown(markdown);
|
|
6441
6548
|
if (codeBlocks.length !== 1) {
|
|
6442
|
-
throw new ParseError(spaceTrim
|
|
6549
|
+
throw new ParseError(spaceTrim((block) => `
|
|
6443
6550
|
There should be exactly 1 code block in task section, found ${codeBlocks.length} code blocks
|
|
6444
6551
|
|
|
6445
6552
|
${block(codeBlocks.map((block, i) => `Block ${i + 1}:\n${block.content}`).join('\n\n\n'))}
|
|
@@ -6521,8 +6628,8 @@ class JavascriptEvalExecutionTools {
|
|
|
6521
6628
|
}
|
|
6522
6629
|
// Note: [💎]
|
|
6523
6630
|
// Note: Using direct eval, following variables are in same scope as eval call so they are accessible from inside the evaluated script:
|
|
6524
|
-
const spaceTrim = (_) => spaceTrim
|
|
6525
|
-
preserve(spaceTrim);
|
|
6631
|
+
const spaceTrim$1 = (_) => spaceTrim(_);
|
|
6632
|
+
preserve(spaceTrim$1);
|
|
6526
6633
|
const removeQuotes$1 = removeQuotes;
|
|
6527
6634
|
preserve(removeQuotes$1);
|
|
6528
6635
|
const unwrapResult$1 = unwrapResult;
|
|
@@ -6575,7 +6682,7 @@ class JavascriptEvalExecutionTools {
|
|
|
6575
6682
|
// TODO: DRY [🍯]
|
|
6576
6683
|
const buildinFunctions = {
|
|
6577
6684
|
// TODO: [🍯] DRY all these functions across the file
|
|
6578
|
-
spaceTrim,
|
|
6685
|
+
spaceTrim: spaceTrim$1,
|
|
6579
6686
|
removeQuotes: removeQuotes$1,
|
|
6580
6687
|
unwrapResult: unwrapResult$1,
|
|
6581
6688
|
trimEndOfCodeBlock: trimEndOfCodeBlock$1,
|
|
@@ -6612,7 +6719,7 @@ class JavascriptEvalExecutionTools {
|
|
|
6612
6719
|
.join('\n');
|
|
6613
6720
|
// script = templateParameters(script, parameters);
|
|
6614
6721
|
// <- TODO: [🧠][🥳] Should be this is one of two variants how to use parameters in script
|
|
6615
|
-
const statementToEvaluate = spaceTrim
|
|
6722
|
+
const statementToEvaluate = spaceTrim((block) => `
|
|
6616
6723
|
|
|
6617
6724
|
// Build-in functions:
|
|
6618
6725
|
${block(buildinFunctionsStatement)}
|
|
@@ -6627,7 +6734,7 @@ class JavascriptEvalExecutionTools {
|
|
|
6627
6734
|
(()=>{ ${script} })()
|
|
6628
6735
|
`);
|
|
6629
6736
|
if (this.options.isVerbose) {
|
|
6630
|
-
console.info(spaceTrim
|
|
6737
|
+
console.info(spaceTrim((block) => `
|
|
6631
6738
|
🚀 Evaluating ${scriptLanguage} script:
|
|
6632
6739
|
|
|
6633
6740
|
${block(statementToEvaluate)}`));
|
|
@@ -6640,9 +6747,7 @@ class JavascriptEvalExecutionTools {
|
|
|
6640
6747
|
}
|
|
6641
6748
|
}
|
|
6642
6749
|
catch (error) {
|
|
6643
|
-
|
|
6644
|
-
throw error;
|
|
6645
|
-
}
|
|
6750
|
+
assertsError(error);
|
|
6646
6751
|
if (error instanceof ReferenceError) {
|
|
6647
6752
|
const undefinedName = error.message.split(' ')[0];
|
|
6648
6753
|
/*
|
|
@@ -6651,7 +6756,7 @@ class JavascriptEvalExecutionTools {
|
|
|
6651
6756
|
To: [PipelineExecutionError: Parameter `{thing}` is not defined],
|
|
6652
6757
|
*/
|
|
6653
6758
|
if (!statementToEvaluate.includes(undefinedName + '(')) {
|
|
6654
|
-
throw new PipelineExecutionError(spaceTrim
|
|
6759
|
+
throw new PipelineExecutionError(spaceTrim((block) => `
|
|
6655
6760
|
|
|
6656
6761
|
Parameter \`{${undefinedName}}\` is not defined
|
|
6657
6762
|
|
|
@@ -6673,7 +6778,7 @@ class JavascriptEvalExecutionTools {
|
|
|
6673
6778
|
`));
|
|
6674
6779
|
}
|
|
6675
6780
|
else {
|
|
6676
|
-
throw new PipelineExecutionError(spaceTrim
|
|
6781
|
+
throw new PipelineExecutionError(spaceTrim((block) => `
|
|
6677
6782
|
Function ${undefinedName}() is not defined
|
|
6678
6783
|
|
|
6679
6784
|
- Make sure that the function is one of built-in functions
|
|
@@ -6722,6 +6827,198 @@ async function $provideScriptingForNode(options) {
|
|
|
6722
6827
|
* Note: [🟢] Code in this file should never be never released in packages that could be imported into browser environment
|
|
6723
6828
|
*/
|
|
6724
6829
|
|
|
6830
|
+
// TODO: !!!! List running services from REMOTE_SERVER_URLS
|
|
6831
|
+
// TODO: !!!! Import directly from YML
|
|
6832
|
+
/**
|
|
6833
|
+
* @private !!!! Decide how to expose this
|
|
6834
|
+
*/
|
|
6835
|
+
const openapiJson = {
|
|
6836
|
+
openapi: '3.0.0',
|
|
6837
|
+
info: {
|
|
6838
|
+
title: 'Promptbook Remote Server API (!!!! From TS)',
|
|
6839
|
+
version: '1.0.0',
|
|
6840
|
+
description: 'API documentation for the Promptbook Remote Server',
|
|
6841
|
+
},
|
|
6842
|
+
paths: {
|
|
6843
|
+
'/': {
|
|
6844
|
+
get: {
|
|
6845
|
+
summary: 'Get server details',
|
|
6846
|
+
description: 'Returns details about the Promptbook server.',
|
|
6847
|
+
responses: {
|
|
6848
|
+
'200': {
|
|
6849
|
+
description: 'Server details in markdown format.',
|
|
6850
|
+
},
|
|
6851
|
+
},
|
|
6852
|
+
},
|
|
6853
|
+
},
|
|
6854
|
+
'/login': {
|
|
6855
|
+
post: {
|
|
6856
|
+
summary: 'Login to the server',
|
|
6857
|
+
description: 'Login to the server and get identification.',
|
|
6858
|
+
requestBody: {
|
|
6859
|
+
required: true,
|
|
6860
|
+
content: {
|
|
6861
|
+
'application/json': {
|
|
6862
|
+
schema: {
|
|
6863
|
+
type: 'object',
|
|
6864
|
+
properties: {
|
|
6865
|
+
username: {
|
|
6866
|
+
type: 'string',
|
|
6867
|
+
},
|
|
6868
|
+
password: {
|
|
6869
|
+
type: 'string',
|
|
6870
|
+
},
|
|
6871
|
+
appId: {
|
|
6872
|
+
type: 'string',
|
|
6873
|
+
},
|
|
6874
|
+
},
|
|
6875
|
+
},
|
|
6876
|
+
},
|
|
6877
|
+
},
|
|
6878
|
+
},
|
|
6879
|
+
responses: {
|
|
6880
|
+
'200': {
|
|
6881
|
+
description: 'Successful login',
|
|
6882
|
+
content: {
|
|
6883
|
+
'application/json': {
|
|
6884
|
+
schema: {
|
|
6885
|
+
type: 'object',
|
|
6886
|
+
properties: {
|
|
6887
|
+
identification: {
|
|
6888
|
+
type: 'object',
|
|
6889
|
+
},
|
|
6890
|
+
},
|
|
6891
|
+
},
|
|
6892
|
+
},
|
|
6893
|
+
},
|
|
6894
|
+
},
|
|
6895
|
+
},
|
|
6896
|
+
},
|
|
6897
|
+
},
|
|
6898
|
+
'/books': {
|
|
6899
|
+
get: {
|
|
6900
|
+
summary: 'List all books',
|
|
6901
|
+
description: 'Returns a list of all available books in the collection.',
|
|
6902
|
+
responses: {
|
|
6903
|
+
'200': {
|
|
6904
|
+
description: 'A list of books.',
|
|
6905
|
+
content: {
|
|
6906
|
+
'application/json': {
|
|
6907
|
+
schema: {
|
|
6908
|
+
type: 'array',
|
|
6909
|
+
items: {
|
|
6910
|
+
type: 'string',
|
|
6911
|
+
},
|
|
6912
|
+
},
|
|
6913
|
+
},
|
|
6914
|
+
},
|
|
6915
|
+
},
|
|
6916
|
+
},
|
|
6917
|
+
},
|
|
6918
|
+
},
|
|
6919
|
+
'/books/{bookId}': {
|
|
6920
|
+
get: {
|
|
6921
|
+
summary: 'Get book content',
|
|
6922
|
+
description: 'Returns the content of a specific book.',
|
|
6923
|
+
parameters: [
|
|
6924
|
+
{
|
|
6925
|
+
in: 'path',
|
|
6926
|
+
name: 'bookId',
|
|
6927
|
+
required: true,
|
|
6928
|
+
schema: {
|
|
6929
|
+
type: 'string',
|
|
6930
|
+
},
|
|
6931
|
+
description: 'The ID of the book to retrieve.',
|
|
6932
|
+
},
|
|
6933
|
+
],
|
|
6934
|
+
responses: {
|
|
6935
|
+
'200': {
|
|
6936
|
+
description: 'The content of the book.',
|
|
6937
|
+
content: {
|
|
6938
|
+
'text/markdown': {
|
|
6939
|
+
schema: {
|
|
6940
|
+
type: 'string',
|
|
6941
|
+
},
|
|
6942
|
+
},
|
|
6943
|
+
},
|
|
6944
|
+
},
|
|
6945
|
+
'404': {
|
|
6946
|
+
description: 'Book not found.',
|
|
6947
|
+
},
|
|
6948
|
+
},
|
|
6949
|
+
},
|
|
6950
|
+
},
|
|
6951
|
+
'/executions': {
|
|
6952
|
+
get: {
|
|
6953
|
+
summary: 'List all executions',
|
|
6954
|
+
description: 'Returns a list of all running execution tasks.',
|
|
6955
|
+
responses: {
|
|
6956
|
+
'200': {
|
|
6957
|
+
description: 'A list of execution tasks.',
|
|
6958
|
+
content: {
|
|
6959
|
+
'application/json': {
|
|
6960
|
+
schema: {
|
|
6961
|
+
type: 'array',
|
|
6962
|
+
items: {
|
|
6963
|
+
type: 'object',
|
|
6964
|
+
},
|
|
6965
|
+
},
|
|
6966
|
+
},
|
|
6967
|
+
},
|
|
6968
|
+
},
|
|
6969
|
+
},
|
|
6970
|
+
},
|
|
6971
|
+
},
|
|
6972
|
+
'/executions/new': {
|
|
6973
|
+
post: {
|
|
6974
|
+
summary: 'Start a new execution',
|
|
6975
|
+
description: 'Starts a new execution task for a given pipeline.',
|
|
6976
|
+
requestBody: {
|
|
6977
|
+
required: true,
|
|
6978
|
+
content: {
|
|
6979
|
+
'application/json': {
|
|
6980
|
+
schema: {
|
|
6981
|
+
type: 'object',
|
|
6982
|
+
properties: {
|
|
6983
|
+
pipelineUrl: {
|
|
6984
|
+
type: 'string',
|
|
6985
|
+
},
|
|
6986
|
+
inputParameters: {
|
|
6987
|
+
type: 'object',
|
|
6988
|
+
},
|
|
6989
|
+
identification: {
|
|
6990
|
+
type: 'object',
|
|
6991
|
+
},
|
|
6992
|
+
},
|
|
6993
|
+
},
|
|
6994
|
+
},
|
|
6995
|
+
},
|
|
6996
|
+
},
|
|
6997
|
+
responses: {
|
|
6998
|
+
'200': {
|
|
6999
|
+
description: 'The newly created execution task.',
|
|
7000
|
+
content: {
|
|
7001
|
+
'application/json': {
|
|
7002
|
+
schema: {
|
|
7003
|
+
type: 'object',
|
|
7004
|
+
},
|
|
7005
|
+
},
|
|
7006
|
+
},
|
|
7007
|
+
},
|
|
7008
|
+
'400': {
|
|
7009
|
+
description: 'Invalid input.',
|
|
7010
|
+
},
|
|
7011
|
+
},
|
|
7012
|
+
},
|
|
7013
|
+
},
|
|
7014
|
+
},
|
|
7015
|
+
components: {},
|
|
7016
|
+
tags: [],
|
|
7017
|
+
};
|
|
7018
|
+
/**
|
|
7019
|
+
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
7020
|
+
*/
|
|
7021
|
+
|
|
6725
7022
|
/**
|
|
6726
7023
|
* Remote server is a proxy server that uses its execution tools internally and exposes the executor interface externally.
|
|
6727
7024
|
*
|
|
@@ -6732,7 +7029,7 @@ async function $provideScriptingForNode(options) {
|
|
|
6732
7029
|
* @public exported from `@promptbook/remote-server`
|
|
6733
7030
|
*/
|
|
6734
7031
|
function startRemoteServer(options) {
|
|
6735
|
-
const { port, collection, createLlmExecutionTools, isAnonymousModeAllowed, isApplicationModeAllowed, isVerbose = DEFAULT_IS_VERBOSE, login, } = {
|
|
7032
|
+
const { port, collection, createLlmExecutionTools, createExecutionTools, isAnonymousModeAllowed, isApplicationModeAllowed, isVerbose = DEFAULT_IS_VERBOSE, login, } = {
|
|
6736
7033
|
isAnonymousModeAllowed: false,
|
|
6737
7034
|
isApplicationModeAllowed: false,
|
|
6738
7035
|
collection: null,
|
|
@@ -6740,22 +7037,6 @@ function startRemoteServer(options) {
|
|
|
6740
7037
|
login: null,
|
|
6741
7038
|
...options,
|
|
6742
7039
|
};
|
|
6743
|
-
// <- TODO: [🦪] Some helper type to be able to use discriminant union types with destructuring
|
|
6744
|
-
let { rootPath = '/' } = options;
|
|
6745
|
-
if (!rootPath.startsWith('/')) {
|
|
6746
|
-
rootPath = `/${rootPath}`;
|
|
6747
|
-
} /* not else */
|
|
6748
|
-
if (rootPath.endsWith('/')) {
|
|
6749
|
-
rootPath = rootPath.slice(0, -1);
|
|
6750
|
-
} /* not else */
|
|
6751
|
-
if (rootPath === '/') {
|
|
6752
|
-
rootPath = '';
|
|
6753
|
-
}
|
|
6754
|
-
const socketioPath = '/' +
|
|
6755
|
-
`${rootPath}/socket.io`
|
|
6756
|
-
.split('/')
|
|
6757
|
-
.filter((part) => part !== '')
|
|
6758
|
-
.join('/');
|
|
6759
7040
|
const startupDate = new Date();
|
|
6760
7041
|
async function getExecutionToolsFromIdentification(identification) {
|
|
6761
7042
|
if (identification === null || identification === undefined) {
|
|
@@ -6778,23 +7059,25 @@ function startRemoteServer(options) {
|
|
|
6778
7059
|
}
|
|
6779
7060
|
else if (isAnonymous === false && createLlmExecutionTools !== null) {
|
|
6780
7061
|
// Note: Application mode
|
|
6781
|
-
|
|
6782
|
-
llm = await createLlmExecutionTools({
|
|
6783
|
-
appId,
|
|
6784
|
-
userId,
|
|
6785
|
-
customOptions,
|
|
6786
|
-
});
|
|
7062
|
+
llm = await createLlmExecutionTools(identification);
|
|
6787
7063
|
}
|
|
6788
7064
|
else {
|
|
6789
7065
|
throw new PipelineExecutionError(`You must provide either llmToolsConfiguration or non-anonymous mode must be propperly configured`);
|
|
6790
7066
|
}
|
|
6791
|
-
const
|
|
6792
|
-
const
|
|
7067
|
+
const customExecutionTools = createExecutionTools ? await createExecutionTools(identification) : {};
|
|
7068
|
+
const fs = customExecutionTools.fs || $provideFilesystemForNode();
|
|
7069
|
+
const executables = customExecutionTools.executables || (await $provideExecutablesForNode());
|
|
7070
|
+
const scrapers = customExecutionTools.scrapers || (await $provideScrapersForNode({ fs, llm, executables }));
|
|
7071
|
+
const script = customExecutionTools.script || (await $provideScriptingForNode({}));
|
|
7072
|
+
const fetch = customExecutionTools.fetch || promptbookFetch;
|
|
7073
|
+
const userInterface = customExecutionTools.userInterface || undefined;
|
|
6793
7074
|
const tools = {
|
|
6794
7075
|
llm,
|
|
6795
7076
|
fs,
|
|
6796
|
-
scrapers
|
|
6797
|
-
script
|
|
7077
|
+
scrapers,
|
|
7078
|
+
script,
|
|
7079
|
+
fetch,
|
|
7080
|
+
userInterface,
|
|
6798
7081
|
};
|
|
6799
7082
|
return tools;
|
|
6800
7083
|
}
|
|
@@ -6804,44 +7087,32 @@ function startRemoteServer(options) {
|
|
|
6804
7087
|
response.setHeader('X-Powered-By', 'Promptbook engine');
|
|
6805
7088
|
next();
|
|
6806
7089
|
});
|
|
6807
|
-
|
|
6808
|
-
|
|
6809
|
-
|
|
6810
|
-
|
|
6811
|
-
|
|
6812
|
-
version: '1.0.0',
|
|
6813
|
-
description: 'API documentation for the Promptbook Remote Server',
|
|
6814
|
-
},
|
|
6815
|
-
servers: [
|
|
6816
|
-
{
|
|
6817
|
-
url: `http://localhost:${port}${rootPath}`,
|
|
6818
|
-
// <- TODO: !!!!! Probbably: Pass `remoteServerUrl` instead of `port` and `rootPath`
|
|
6819
|
-
},
|
|
6820
|
-
],
|
|
7090
|
+
// TODO: !!!! Expose openapiJson to consumer and also allow to add new routes
|
|
7091
|
+
app.use(OpenApiValidator.middleware({
|
|
7092
|
+
apiSpec: openapiJson,
|
|
7093
|
+
ignorePaths(path) {
|
|
7094
|
+
return path.startsWith('/api-docs') || path.startsWith('/swagger') || path.startsWith('/openapi');
|
|
6821
7095
|
},
|
|
6822
|
-
|
|
6823
|
-
|
|
6824
|
-
|
|
6825
|
-
app.use([`/api-docs`,
|
|
7096
|
+
validateRequests: true,
|
|
7097
|
+
validateResponses: true,
|
|
7098
|
+
}));
|
|
7099
|
+
app.use([`/api-docs`, `/swagger`], swaggerUi.serve, swaggerUi.setup(openapiJson, {
|
|
7100
|
+
// customCss: '.swagger-ui .topbar { display: none }',
|
|
7101
|
+
// customSiteTitle: 'BRJ API',
|
|
7102
|
+
// customfavIcon: 'https://brj.app/favicon.ico',
|
|
7103
|
+
}));
|
|
7104
|
+
app.get(`/openapi`, (request, response) => {
|
|
7105
|
+
response.json(openapiJson);
|
|
7106
|
+
});
|
|
6826
7107
|
const runningExecutionTasks = [];
|
|
6827
7108
|
// <- TODO: [🤬] Identify the users
|
|
6828
7109
|
// TODO: [🧠] Do here some garbage collection of finished tasks
|
|
6829
|
-
|
|
6830
|
-
* @swagger
|
|
6831
|
-
* /:
|
|
6832
|
-
* get:
|
|
6833
|
-
* summary: Get server details
|
|
6834
|
-
* description: Returns details about the Promptbook server.
|
|
6835
|
-
* responses:
|
|
6836
|
-
* 200:
|
|
6837
|
-
* description: Server details in markdown format.
|
|
6838
|
-
*/
|
|
6839
|
-
app.get(['/', rootPath], async (request, response) => {
|
|
7110
|
+
app.get('/', async (request, response) => {
|
|
6840
7111
|
var _a;
|
|
6841
7112
|
if ((_a = request.url) === null || _a === void 0 ? void 0 : _a.includes('socket.io')) {
|
|
6842
7113
|
return;
|
|
6843
7114
|
}
|
|
6844
|
-
response.type('text/markdown').send(await spaceTrim(async (block) => `
|
|
7115
|
+
response.type('text/markdown').send(await spaceTrim$1(async (block) => `
|
|
6845
7116
|
# Promptbook
|
|
6846
7117
|
|
|
6847
7118
|
> ${block(CLAIM)}
|
|
@@ -6855,8 +7126,6 @@ function startRemoteServer(options) {
|
|
|
6855
7126
|
## Details
|
|
6856
7127
|
|
|
6857
7128
|
**Server port:** ${port}
|
|
6858
|
-
**Server root path:** ${rootPath}
|
|
6859
|
-
**Socket.io path:** ${socketioPath}
|
|
6860
7129
|
**Startup date:** ${startupDate.toISOString()}
|
|
6861
7130
|
**Anonymouse mode:** ${isAnonymousModeAllowed ? 'enabled' : 'disabled'}
|
|
6862
7131
|
**Application mode:** ${isApplicationModeAllowed ? 'enabled' : 'disabled'}
|
|
@@ -6895,38 +7164,7 @@ function startRemoteServer(options) {
|
|
|
6895
7164
|
https://github.com/webgptorg/promptbook
|
|
6896
7165
|
`));
|
|
6897
7166
|
});
|
|
6898
|
-
|
|
6899
|
-
* @swagger
|
|
6900
|
-
*
|
|
6901
|
-
* /login:
|
|
6902
|
-
* post:
|
|
6903
|
-
* summary: Login to the server
|
|
6904
|
-
* description: Login to the server and get identification.
|
|
6905
|
-
* requestBody:
|
|
6906
|
-
* required: true
|
|
6907
|
-
* content:
|
|
6908
|
-
* application/json:
|
|
6909
|
-
* schema:
|
|
6910
|
-
* type: object
|
|
6911
|
-
* properties:
|
|
6912
|
-
* username:
|
|
6913
|
-
* type: string
|
|
6914
|
-
* password:
|
|
6915
|
-
* type: string
|
|
6916
|
-
* appId:
|
|
6917
|
-
* type: string
|
|
6918
|
-
* responses:
|
|
6919
|
-
* 200:
|
|
6920
|
-
* description: Successful login
|
|
6921
|
-
* content:
|
|
6922
|
-
* application/json:
|
|
6923
|
-
* schema:
|
|
6924
|
-
* type: object
|
|
6925
|
-
* properties:
|
|
6926
|
-
* identification:
|
|
6927
|
-
* type: object
|
|
6928
|
-
*/
|
|
6929
|
-
app.post([`/login`, `${rootPath}/login`], async (request, response) => {
|
|
7167
|
+
app.post(`/login`, async (request, response) => {
|
|
6930
7168
|
if (!isApplicationModeAllowed || login === null) {
|
|
6931
7169
|
response.status(400).send('Application mode is not allowed');
|
|
6932
7170
|
return;
|
|
@@ -6951,9 +7189,7 @@ function startRemoteServer(options) {
|
|
|
6951
7189
|
return;
|
|
6952
7190
|
}
|
|
6953
7191
|
catch (error) {
|
|
6954
|
-
|
|
6955
|
-
throw error;
|
|
6956
|
-
}
|
|
7192
|
+
assertsError(error);
|
|
6957
7193
|
if (error instanceof AuthenticationError) {
|
|
6958
7194
|
response.status(401).send({
|
|
6959
7195
|
isSuccess: false,
|
|
@@ -6968,23 +7204,7 @@ function startRemoteServer(options) {
|
|
|
6968
7204
|
response.status(400).send({ error: serializeError(error) });
|
|
6969
7205
|
}
|
|
6970
7206
|
});
|
|
6971
|
-
|
|
6972
|
-
* @swagger
|
|
6973
|
-
* /books:
|
|
6974
|
-
* get:
|
|
6975
|
-
* summary: List all books
|
|
6976
|
-
* description: Returns a list of all available books in the collection.
|
|
6977
|
-
* responses:
|
|
6978
|
-
* 200:
|
|
6979
|
-
* description: A list of books.
|
|
6980
|
-
* content:
|
|
6981
|
-
* application/json:
|
|
6982
|
-
* schema:
|
|
6983
|
-
* type: array
|
|
6984
|
-
* items:
|
|
6985
|
-
* type: string
|
|
6986
|
-
*/
|
|
6987
|
-
app.get([`/books`, `${rootPath}/books`], async (request, response) => {
|
|
7207
|
+
app.get(`/books`, async (request, response) => {
|
|
6988
7208
|
if (collection === null) {
|
|
6989
7209
|
response.status(500).send('No collection available');
|
|
6990
7210
|
return;
|
|
@@ -6994,30 +7214,7 @@ function startRemoteServer(options) {
|
|
|
6994
7214
|
response.send(pipelines);
|
|
6995
7215
|
});
|
|
6996
7216
|
// TODO: [🧠] Is it secure / good idea to expose source codes of hosted books
|
|
6997
|
-
|
|
6998
|
-
* @swagger
|
|
6999
|
-
* /books/{bookId}:
|
|
7000
|
-
* get:
|
|
7001
|
-
* summary: Get book content
|
|
7002
|
-
* description: Returns the content of a specific book.
|
|
7003
|
-
* parameters:
|
|
7004
|
-
* - in: path
|
|
7005
|
-
* name: bookId
|
|
7006
|
-
* required: true
|
|
7007
|
-
* schema:
|
|
7008
|
-
* type: string
|
|
7009
|
-
* description: The ID of the book to retrieve.
|
|
7010
|
-
* responses:
|
|
7011
|
-
* 200:
|
|
7012
|
-
* description: The content of the book.
|
|
7013
|
-
* content:
|
|
7014
|
-
* text/markdown:
|
|
7015
|
-
* schema:
|
|
7016
|
-
* type: string
|
|
7017
|
-
* 404:
|
|
7018
|
-
* description: Book not found.
|
|
7019
|
-
*/
|
|
7020
|
-
app.get([`/books/*`, `${rootPath}/books/*`], async (request, response) => {
|
|
7217
|
+
app.get(`/books/*`, async (request, response) => {
|
|
7021
7218
|
try {
|
|
7022
7219
|
if (collection === null) {
|
|
7023
7220
|
response.status(500).send('No collection nor books available');
|
|
@@ -7036,9 +7233,7 @@ function startRemoteServer(options) {
|
|
|
7036
7233
|
.send(source.content);
|
|
7037
7234
|
}
|
|
7038
7235
|
catch (error) {
|
|
7039
|
-
|
|
7040
|
-
throw error;
|
|
7041
|
-
}
|
|
7236
|
+
assertsError(error);
|
|
7042
7237
|
response
|
|
7043
7238
|
.status(404)
|
|
7044
7239
|
.send({ error: serializeError(error) });
|
|
@@ -7071,26 +7266,10 @@ function startRemoteServer(options) {
|
|
|
7071
7266
|
};
|
|
7072
7267
|
}
|
|
7073
7268
|
}
|
|
7074
|
-
|
|
7075
|
-
|
|
7076
|
-
* /executions:
|
|
7077
|
-
* get:
|
|
7078
|
-
* summary: List all executions
|
|
7079
|
-
* description: Returns a list of all running execution tasks.
|
|
7080
|
-
* responses:
|
|
7081
|
-
* 200:
|
|
7082
|
-
* description: A list of execution tasks.
|
|
7083
|
-
* content:
|
|
7084
|
-
* application/json:
|
|
7085
|
-
* schema:
|
|
7086
|
-
* type: array
|
|
7087
|
-
* items:
|
|
7088
|
-
* type: object
|
|
7089
|
-
*/
|
|
7090
|
-
app.get([`/executions`, `${rootPath}/executions`], async (request, response) => {
|
|
7091
|
-
response.send(runningExecutionTasks.map((runningExecutionTask) => exportExecutionTask(runningExecutionTask, false)));
|
|
7269
|
+
app.get(`/executions`, async (request, response) => {
|
|
7270
|
+
response.send(runningExecutionTasks.map((runningExecutionTask) => exportExecutionTask(runningExecutionTask, false)) /* <- TODO: satisfies paths['/executions']['get']['responses']['200']['content']['application/json'] */);
|
|
7092
7271
|
});
|
|
7093
|
-
app.get(
|
|
7272
|
+
app.get(`/executions/last`, async (request, response) => {
|
|
7094
7273
|
// TODO: [🤬] Filter only for user
|
|
7095
7274
|
if (runningExecutionTasks.length === 0) {
|
|
7096
7275
|
response.status(404).send('No execution tasks found');
|
|
@@ -7099,7 +7278,7 @@ function startRemoteServer(options) {
|
|
|
7099
7278
|
const lastExecutionTask = runningExecutionTasks[runningExecutionTasks.length - 1];
|
|
7100
7279
|
response.send(exportExecutionTask(lastExecutionTask, true));
|
|
7101
7280
|
});
|
|
7102
|
-
app.get(
|
|
7281
|
+
app.get(`/executions/:taskId`, async (request, response) => {
|
|
7103
7282
|
const { taskId } = request.params;
|
|
7104
7283
|
// TODO: [🤬] Filter only for user
|
|
7105
7284
|
const executionTask = runningExecutionTasks.find((executionTask) => executionTask.taskId === taskId);
|
|
@@ -7111,39 +7290,12 @@ function startRemoteServer(options) {
|
|
|
7111
7290
|
}
|
|
7112
7291
|
response.send(exportExecutionTask(executionTask, true));
|
|
7113
7292
|
});
|
|
7114
|
-
|
|
7115
|
-
* @swagger
|
|
7116
|
-
* /executions/new:
|
|
7117
|
-
* post:
|
|
7118
|
-
* summary: Start a new execution
|
|
7119
|
-
* description: Starts a new execution task for a given pipeline.
|
|
7120
|
-
* requestBody:
|
|
7121
|
-
* required: true
|
|
7122
|
-
* content:
|
|
7123
|
-
* application/json:
|
|
7124
|
-
* schema:
|
|
7125
|
-
* type: object
|
|
7126
|
-
* properties:
|
|
7127
|
-
* pipelineUrl:
|
|
7128
|
-
* type: string
|
|
7129
|
-
* inputParameters:
|
|
7130
|
-
* type: object
|
|
7131
|
-
* identification:
|
|
7132
|
-
* type: object
|
|
7133
|
-
* responses:
|
|
7134
|
-
* 200:
|
|
7135
|
-
* description: The newly created execution task.
|
|
7136
|
-
* content:
|
|
7137
|
-
* application/json:
|
|
7138
|
-
* schema:
|
|
7139
|
-
* type: object
|
|
7140
|
-
* 400:
|
|
7141
|
-
* description: Invalid input.
|
|
7142
|
-
*/
|
|
7143
|
-
app.post([`/executions/new`, `${rootPath}/executions/new`], async (request, response) => {
|
|
7293
|
+
app.post(`/executions/new`, async (request, response) => {
|
|
7144
7294
|
try {
|
|
7145
7295
|
const { inputParameters, identification /* <- [🤬] */ } = request.body;
|
|
7146
|
-
const pipelineUrl = request.body
|
|
7296
|
+
const pipelineUrl = request.body
|
|
7297
|
+
.pipelineUrl /* <- TODO: as paths['/executions/new']['post']['requestBody']['content']['application/json'] */ ||
|
|
7298
|
+
request.body.book;
|
|
7147
7299
|
// TODO: [🧠] Check `pipelineUrl` and `inputParameters` here or it should be responsibility of `collection.getPipelineByUrl` and `pipelineExecutor`
|
|
7148
7300
|
const pipeline = await (collection === null || collection === void 0 ? void 0 : collection.getPipelineByUrl(pipelineUrl));
|
|
7149
7301
|
if (pipeline === undefined) {
|
|
@@ -7157,7 +7309,7 @@ function startRemoteServer(options) {
|
|
|
7157
7309
|
await forTime(10);
|
|
7158
7310
|
// <- Note: Wait for a while to wait for quick responses or sudden but asynchronous errors
|
|
7159
7311
|
// <- TODO: Put this into configuration
|
|
7160
|
-
response.send(executionTask);
|
|
7312
|
+
response.send(executionTask /* <- TODO: satisfies paths['/executions/new']['post']['responses']['200']['content']['application/json'] */);
|
|
7161
7313
|
/*/
|
|
7162
7314
|
executionTask.asObservable().subscribe({
|
|
7163
7315
|
next(partialResult) {
|
|
@@ -7177,19 +7329,24 @@ function startRemoteServer(options) {
|
|
|
7177
7329
|
*/
|
|
7178
7330
|
}
|
|
7179
7331
|
catch (error) {
|
|
7180
|
-
|
|
7181
|
-
throw error;
|
|
7182
|
-
}
|
|
7332
|
+
assertsError(error);
|
|
7183
7333
|
response.status(400).send({ error: serializeError(error) });
|
|
7184
7334
|
}
|
|
7185
7335
|
});
|
|
7336
|
+
/**
|
|
7337
|
+
* Catch-all handler for unmatched routes
|
|
7338
|
+
*/
|
|
7339
|
+
app.use((request, response) => {
|
|
7340
|
+
response.status(404).send(`URL "${request.originalUrl}" was not found on Promptbook server.`);
|
|
7341
|
+
});
|
|
7186
7342
|
const httpServer = http.createServer(app);
|
|
7187
7343
|
const server = new Server(httpServer, {
|
|
7188
|
-
path:
|
|
7189
|
-
transports: [
|
|
7344
|
+
path: '/socket.io',
|
|
7345
|
+
transports: ['polling', 'websocket' /*, <- TODO: [🌬] Allow to pass `transports`, add 'webtransport' */],
|
|
7190
7346
|
cors: {
|
|
7191
7347
|
origin: '*',
|
|
7192
7348
|
methods: ['GET', 'POST'],
|
|
7349
|
+
// <- TODO: [🌡] Allow to pass
|
|
7193
7350
|
},
|
|
7194
7351
|
});
|
|
7195
7352
|
server.on('connection', (socket) => {
|
|
@@ -7243,9 +7400,7 @@ function startRemoteServer(options) {
|
|
|
7243
7400
|
socket.emit('prompt-response', { promptResult } /* <- Note: [🤛] */);
|
|
7244
7401
|
}
|
|
7245
7402
|
catch (error) {
|
|
7246
|
-
|
|
7247
|
-
throw error;
|
|
7248
|
-
}
|
|
7403
|
+
assertsError(error);
|
|
7249
7404
|
socket.emit('error', serializeError(error) /* <- Note: [🤛] */);
|
|
7250
7405
|
}
|
|
7251
7406
|
finally {
|
|
@@ -7267,9 +7422,7 @@ function startRemoteServer(options) {
|
|
|
7267
7422
|
socket.emit('listModels-response', { models } /* <- Note: [🤛] */);
|
|
7268
7423
|
}
|
|
7269
7424
|
catch (error) {
|
|
7270
|
-
|
|
7271
|
-
throw error;
|
|
7272
|
-
}
|
|
7425
|
+
assertsError(error);
|
|
7273
7426
|
socket.emit('error', serializeError(error));
|
|
7274
7427
|
}
|
|
7275
7428
|
finally {
|
|
@@ -7290,9 +7443,7 @@ function startRemoteServer(options) {
|
|
|
7290
7443
|
socket.emit('preparePipeline-response', { preparedPipeline } /* <- Note: [🤛] */);
|
|
7291
7444
|
}
|
|
7292
7445
|
catch (error) {
|
|
7293
|
-
|
|
7294
|
-
throw error;
|
|
7295
|
-
}
|
|
7446
|
+
assertsError(error);
|
|
7296
7447
|
socket.emit('error', serializeError(error));
|
|
7297
7448
|
// <- TODO: [🚋] There is a problem with the remote server handling errors and sending them back to the client
|
|
7298
7449
|
}
|
|
@@ -7340,8 +7491,7 @@ function startRemoteServer(options) {
|
|
|
7340
7491
|
};
|
|
7341
7492
|
}
|
|
7342
7493
|
/**
|
|
7343
|
-
* TODO:
|
|
7344
|
-
* TODO: [👩🏾🤝🧑🏾] Allow to pass custom fetch function here - PromptbookFetch
|
|
7494
|
+
* TODO: [🌡] Add CORS and security - probbably via `helmet`
|
|
7345
7495
|
* TODO: Split this file into multiple functions - handler for each request
|
|
7346
7496
|
* TODO: Maybe use `$exportJson`
|
|
7347
7497
|
* TODO: [🧠][🛍] Maybe not `isAnonymous: boolean` BUT `mode: 'ANONYMOUS'|'COLLECTION'`
|