@promptbook/remote-server 0.89.0-9 โ 0.92.0-10
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 -7
- package/esm/index.es.js +1133 -455
- 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 +14 -4
- package/esm/typings/src/_packages/deepseek.index.d.ts +2 -0
- package/esm/typings/src/_packages/google.index.d.ts +2 -0
- package/esm/typings/src/_packages/types.index.d.ts +18 -0
- package/esm/typings/src/_packages/utils.index.d.ts +6 -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/conversion/archive/loadArchive.d.ts +2 -2
- package/esm/typings/src/errors/0-index.d.ts +7 -4
- package/esm/typings/src/errors/PipelineExecutionError.d.ts +1 -1
- 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/CommonToolsOptions.d.ts +4 -0
- package/esm/typings/src/execution/PromptbookFetch.d.ts +1 -1
- package/esm/typings/src/execution/createPipelineExecutor/getKnowledgeForTask.d.ts +12 -0
- package/esm/typings/src/execution/createPipelineExecutor/getReservedParametersForTask.d.ts +5 -0
- package/esm/typings/src/formats/csv/utils/csvParse.d.ts +12 -0
- 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/json/utils/jsonParse.d.ts +11 -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/filterModels.d.ts +15 -0
- package/esm/typings/src/llm-providers/_common/register/{$provideEnvFilepath.d.ts โ $provideEnvFilename.d.ts} +2 -2
- package/esm/typings/src/llm-providers/_common/register/$provideLlmToolsConfigurationFromEnv.d.ts +1 -1
- package/esm/typings/src/llm-providers/_common/register/$provideLlmToolsForTestingAndScriptsAndPlayground.d.ts +1 -1
- package/esm/typings/src/llm-providers/_common/register/$provideLlmToolsForWizzardOrCli.d.ts +11 -2
- package/esm/typings/src/llm-providers/_common/register/$provideLlmToolsFromEnv.d.ts +1 -1
- package/esm/typings/src/llm-providers/_common/register/LlmToolsMetadata.d.ts +43 -0
- package/esm/typings/src/llm-providers/azure-openai/AzureOpenAiExecutionTools.d.ts +4 -0
- package/esm/typings/src/llm-providers/deepseek/deepseek-models.d.ts +23 -0
- package/esm/typings/src/llm-providers/google/google-models.d.ts +23 -0
- package/esm/typings/src/llm-providers/openai/OpenAiExecutionTools.d.ts +4 -0
- package/esm/typings/src/personas/preparePersona.d.ts +1 -1
- package/esm/typings/src/pipeline/PipelineJson/PersonaJson.d.ts +4 -2
- package/esm/typings/src/remote-server/openapi-types.d.ts +626 -0
- package/esm/typings/src/remote-server/openapi.d.ts +581 -0
- package/esm/typings/src/remote-server/socket-types/_subtypes/Identification.d.ts +7 -1
- 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/startRemoteServer.d.ts +1 -2
- package/esm/typings/src/remote-server/types/RemoteServerOptions.d.ts +15 -9
- 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 +1054 -358
- package/umd/index.umd.js.map +1 -1
- package/esm/typings/src/cli/test/ptbk2.d.ts +0 -5
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.
|
|
36
|
+
const PROMPTBOOK_ENGINE_VERSION = '0.92.0-10';
|
|
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.
|
|
@@ -467,74 +585,6 @@ class PromptbookFetchError extends Error {
|
|
|
467
585
|
}
|
|
468
586
|
}
|
|
469
587
|
|
|
470
|
-
/**
|
|
471
|
-
* Make error report URL for the given error
|
|
472
|
-
*
|
|
473
|
-
* @private private within the repository
|
|
474
|
-
*/
|
|
475
|
-
function getErrorReportUrl(error) {
|
|
476
|
-
const report = {
|
|
477
|
-
title: `๐ Error report from ${NAME}`,
|
|
478
|
-
body: spaceTrim$1((block) => `
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
\`${error.name || 'Error'}\` has occurred in the [${NAME}], please look into it @${ADMIN_GITHUB_NAME}.
|
|
482
|
-
|
|
483
|
-
\`\`\`
|
|
484
|
-
${block(error.message || '(no error message)')}
|
|
485
|
-
\`\`\`
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
## More info:
|
|
489
|
-
|
|
490
|
-
- **Promptbook engine version:** ${PROMPTBOOK_ENGINE_VERSION}
|
|
491
|
-
- **Book language version:** ${BOOK_LANGUAGE_VERSION}
|
|
492
|
-
- **Time:** ${new Date().toISOString()}
|
|
493
|
-
|
|
494
|
-
<details>
|
|
495
|
-
<summary>Stack trace:</summary>
|
|
496
|
-
|
|
497
|
-
## Stack trace:
|
|
498
|
-
|
|
499
|
-
\`\`\`stacktrace
|
|
500
|
-
${block(error.stack || '(empty)')}
|
|
501
|
-
\`\`\`
|
|
502
|
-
</details>
|
|
503
|
-
|
|
504
|
-
`),
|
|
505
|
-
};
|
|
506
|
-
const reportUrl = new URL(`https://github.com/webgptorg/promptbook/issues/new`);
|
|
507
|
-
reportUrl.searchParams.set('labels', 'bug');
|
|
508
|
-
reportUrl.searchParams.set('assignees', ADMIN_GITHUB_NAME);
|
|
509
|
-
reportUrl.searchParams.set('title', report.title);
|
|
510
|
-
reportUrl.searchParams.set('body', report.body);
|
|
511
|
-
return reportUrl;
|
|
512
|
-
}
|
|
513
|
-
|
|
514
|
-
/**
|
|
515
|
-
* This error type indicates that the error should not happen and its last check before crashing with some other error
|
|
516
|
-
*
|
|
517
|
-
* @public exported from `@promptbook/core`
|
|
518
|
-
*/
|
|
519
|
-
class UnexpectedError extends Error {
|
|
520
|
-
constructor(message) {
|
|
521
|
-
super(spaceTrim((block) => `
|
|
522
|
-
${block(message)}
|
|
523
|
-
|
|
524
|
-
Note: This error should not happen.
|
|
525
|
-
It's probbably a bug in the pipeline collection
|
|
526
|
-
|
|
527
|
-
Please report issue:
|
|
528
|
-
${block(getErrorReportUrl(new Error(message)).href)}
|
|
529
|
-
|
|
530
|
-
Or contact us on ${ADMIN_EMAIL}
|
|
531
|
-
|
|
532
|
-
`));
|
|
533
|
-
this.name = 'UnexpectedError';
|
|
534
|
-
Object.setPrototypeOf(this, UnexpectedError.prototype);
|
|
535
|
-
}
|
|
536
|
-
}
|
|
537
|
-
|
|
538
588
|
/**
|
|
539
589
|
* Index of all custom errors
|
|
540
590
|
*
|
|
@@ -555,7 +605,10 @@ const PROMPTBOOK_ERRORS = {
|
|
|
555
605
|
PipelineExecutionError,
|
|
556
606
|
PipelineLogicError,
|
|
557
607
|
PipelineUrlError,
|
|
608
|
+
AuthenticationError,
|
|
609
|
+
PromptbookFetchError,
|
|
558
610
|
UnexpectedError,
|
|
611
|
+
WrappedError,
|
|
559
612
|
// TODO: [๐ช]> VersionMismatchError,
|
|
560
613
|
};
|
|
561
614
|
/**
|
|
@@ -572,8 +625,6 @@ const COMMON_JAVASCRIPT_ERRORS = {
|
|
|
572
625
|
TypeError,
|
|
573
626
|
URIError,
|
|
574
627
|
AggregateError,
|
|
575
|
-
AuthenticationError,
|
|
576
|
-
PromptbookFetchError,
|
|
577
628
|
/*
|
|
578
629
|
Note: Not widely supported
|
|
579
630
|
> InternalError,
|
|
@@ -605,7 +656,7 @@ function serializeError(error) {
|
|
|
605
656
|
const { name, message, stack } = error;
|
|
606
657
|
const { id } = error;
|
|
607
658
|
if (!Object.keys(ALL_ERRORS).includes(name)) {
|
|
608
|
-
console.error(spaceTrim
|
|
659
|
+
console.error(spaceTrim((block) => `
|
|
609
660
|
|
|
610
661
|
Cannot serialize error with name "${name}"
|
|
611
662
|
|
|
@@ -769,11 +820,11 @@ function $execCommand(options) {
|
|
|
769
820
|
console.warn(`Command "${humanReadableCommand}" exited with code ${code}`);
|
|
770
821
|
// <- TODO: [๐ฎ] Some standard way how to transform errors into warnings and how to handle non-critical fails during the tasks
|
|
771
822
|
}
|
|
772
|
-
resolve(spaceTrim(output.join('\n')));
|
|
823
|
+
resolve(spaceTrim$1(output.join('\n')));
|
|
773
824
|
}
|
|
774
825
|
}
|
|
775
826
|
else {
|
|
776
|
-
resolve(spaceTrim(output.join('\n')));
|
|
827
|
+
resolve(spaceTrim$1(output.join('\n')));
|
|
777
828
|
}
|
|
778
829
|
};
|
|
779
830
|
commandProcess.on('close', finishWithCode);
|
|
@@ -791,7 +842,7 @@ function $execCommand(options) {
|
|
|
791
842
|
console.warn(error);
|
|
792
843
|
// <- TODO: [๐ฎ] Some standard way how to transform errors into warnings and how to handle non-critical fails during the tasks
|
|
793
844
|
}
|
|
794
|
-
resolve(spaceTrim(output.join('\n')));
|
|
845
|
+
resolve(spaceTrim$1(output.join('\n')));
|
|
795
846
|
}
|
|
796
847
|
});
|
|
797
848
|
}
|
|
@@ -816,9 +867,7 @@ async function locateAppOnLinux({ linuxWhich, }) {
|
|
|
816
867
|
return result.trim();
|
|
817
868
|
}
|
|
818
869
|
catch (error) {
|
|
819
|
-
|
|
820
|
-
throw error;
|
|
821
|
-
}
|
|
870
|
+
assertsError(error);
|
|
822
871
|
return null;
|
|
823
872
|
}
|
|
824
873
|
}
|
|
@@ -896,9 +945,7 @@ async function locateAppOnMacOs({ macOsName, }) {
|
|
|
896
945
|
return result.trim() + toExec;
|
|
897
946
|
}
|
|
898
947
|
catch (error) {
|
|
899
|
-
|
|
900
|
-
throw error;
|
|
901
|
-
}
|
|
948
|
+
assertsError(error);
|
|
902
949
|
return null;
|
|
903
950
|
}
|
|
904
951
|
}
|
|
@@ -929,9 +976,7 @@ async function locateAppOnWindows({ appName, windowsSuffix, }) {
|
|
|
929
976
|
throw new Error(`Can not locate app ${appName} on Windows.`);
|
|
930
977
|
}
|
|
931
978
|
catch (error) {
|
|
932
|
-
|
|
933
|
-
throw error;
|
|
934
|
-
}
|
|
979
|
+
assertsError(error);
|
|
935
980
|
return null;
|
|
936
981
|
}
|
|
937
982
|
}
|
|
@@ -1128,7 +1173,7 @@ function checkSerializableAsJson(options) {
|
|
|
1128
1173
|
}
|
|
1129
1174
|
else if (typeof value === 'object') {
|
|
1130
1175
|
if (value instanceof Date) {
|
|
1131
|
-
throw new UnexpectedError(spaceTrim
|
|
1176
|
+
throw new UnexpectedError(spaceTrim((block) => `
|
|
1132
1177
|
\`${name}\` is Date
|
|
1133
1178
|
|
|
1134
1179
|
Use \`string_date_iso8601\` instead
|
|
@@ -1147,7 +1192,7 @@ function checkSerializableAsJson(options) {
|
|
|
1147
1192
|
throw new UnexpectedError(`${name} is RegExp`);
|
|
1148
1193
|
}
|
|
1149
1194
|
else if (value instanceof Error) {
|
|
1150
|
-
throw new UnexpectedError(spaceTrim
|
|
1195
|
+
throw new UnexpectedError(spaceTrim((block) => `
|
|
1151
1196
|
\`${name}\` is unserialized Error
|
|
1152
1197
|
|
|
1153
1198
|
Use function \`serializeError\`
|
|
@@ -1169,10 +1214,8 @@ function checkSerializableAsJson(options) {
|
|
|
1169
1214
|
JSON.stringify(value); // <- TODO: [0]
|
|
1170
1215
|
}
|
|
1171
1216
|
catch (error) {
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
}
|
|
1175
|
-
throw new UnexpectedError(spaceTrim$1((block) => `
|
|
1217
|
+
assertsError(error);
|
|
1218
|
+
throw new UnexpectedError(spaceTrim((block) => `
|
|
1176
1219
|
\`${name}\` is not serializable
|
|
1177
1220
|
|
|
1178
1221
|
${block(error.stack || error.message)}
|
|
@@ -1204,7 +1247,7 @@ function checkSerializableAsJson(options) {
|
|
|
1204
1247
|
}
|
|
1205
1248
|
}
|
|
1206
1249
|
else {
|
|
1207
|
-
throw new UnexpectedError(spaceTrim
|
|
1250
|
+
throw new UnexpectedError(spaceTrim((block) => `
|
|
1208
1251
|
\`${name}\` is unknown type
|
|
1209
1252
|
|
|
1210
1253
|
Additional message for \`${name}\`:
|
|
@@ -1467,7 +1510,7 @@ function validatePipeline(pipeline) {
|
|
|
1467
1510
|
if (!(error instanceof PipelineLogicError)) {
|
|
1468
1511
|
throw error;
|
|
1469
1512
|
}
|
|
1470
|
-
console.error(spaceTrim((block) => `
|
|
1513
|
+
console.error(spaceTrim$1((block) => `
|
|
1471
1514
|
Pipeline is not valid but logic errors are temporarily disabled via \`IS_PIPELINE_LOGIC_VALIDATED\`
|
|
1472
1515
|
|
|
1473
1516
|
${block(error.message)}
|
|
@@ -1494,7 +1537,7 @@ function validatePipeline_InnerFunction(pipeline) {
|
|
|
1494
1537
|
})();
|
|
1495
1538
|
if (pipeline.pipelineUrl !== undefined && !isValidPipelineUrl(pipeline.pipelineUrl)) {
|
|
1496
1539
|
// <- Note: [๐ฒ]
|
|
1497
|
-
throw new PipelineLogicError(spaceTrim((block) => `
|
|
1540
|
+
throw new PipelineLogicError(spaceTrim$1((block) => `
|
|
1498
1541
|
Invalid promptbook URL "${pipeline.pipelineUrl}"
|
|
1499
1542
|
|
|
1500
1543
|
${block(pipelineIdentification)}
|
|
@@ -1502,7 +1545,7 @@ function validatePipeline_InnerFunction(pipeline) {
|
|
|
1502
1545
|
}
|
|
1503
1546
|
if (pipeline.bookVersion !== undefined && !isValidPromptbookVersion(pipeline.bookVersion)) {
|
|
1504
1547
|
// <- Note: [๐ฒ]
|
|
1505
|
-
throw new PipelineLogicError(spaceTrim((block) => `
|
|
1548
|
+
throw new PipelineLogicError(spaceTrim$1((block) => `
|
|
1506
1549
|
Invalid Promptbook Version "${pipeline.bookVersion}"
|
|
1507
1550
|
|
|
1508
1551
|
${block(pipelineIdentification)}
|
|
@@ -1511,7 +1554,7 @@ function validatePipeline_InnerFunction(pipeline) {
|
|
|
1511
1554
|
// TODO: [๐ง ] Maybe do here some propper JSON-schema / ZOD checking
|
|
1512
1555
|
if (!Array.isArray(pipeline.parameters)) {
|
|
1513
1556
|
// TODO: [๐ง ] what is the correct error tp throw - maybe PromptbookSchemaError
|
|
1514
|
-
throw new ParseError(spaceTrim((block) => `
|
|
1557
|
+
throw new ParseError(spaceTrim$1((block) => `
|
|
1515
1558
|
Pipeline is valid JSON but with wrong structure
|
|
1516
1559
|
|
|
1517
1560
|
\`PipelineJson.parameters\` expected to be an array, but got ${typeof pipeline.parameters}
|
|
@@ -1522,7 +1565,7 @@ function validatePipeline_InnerFunction(pipeline) {
|
|
|
1522
1565
|
// TODO: [๐ง ] Maybe do here some propper JSON-schema / ZOD checking
|
|
1523
1566
|
if (!Array.isArray(pipeline.tasks)) {
|
|
1524
1567
|
// TODO: [๐ง ] what is the correct error tp throw - maybe PromptbookSchemaError
|
|
1525
|
-
throw new ParseError(spaceTrim((block) => `
|
|
1568
|
+
throw new ParseError(spaceTrim$1((block) => `
|
|
1526
1569
|
Pipeline is valid JSON but with wrong structure
|
|
1527
1570
|
|
|
1528
1571
|
\`PipelineJson.tasks\` expected to be an array, but got ${typeof pipeline.tasks}
|
|
@@ -1548,7 +1591,7 @@ function validatePipeline_InnerFunction(pipeline) {
|
|
|
1548
1591
|
// Note: Check each parameter individually
|
|
1549
1592
|
for (const parameter of pipeline.parameters) {
|
|
1550
1593
|
if (parameter.isInput && parameter.isOutput) {
|
|
1551
|
-
throw new PipelineLogicError(spaceTrim((block) => `
|
|
1594
|
+
throw new PipelineLogicError(spaceTrim$1((block) => `
|
|
1552
1595
|
|
|
1553
1596
|
Parameter \`{${parameter.name}}\` can not be both input and output
|
|
1554
1597
|
|
|
@@ -1559,7 +1602,7 @@ function validatePipeline_InnerFunction(pipeline) {
|
|
|
1559
1602
|
if (!parameter.isInput &&
|
|
1560
1603
|
!parameter.isOutput &&
|
|
1561
1604
|
!pipeline.tasks.some((task) => task.dependentParameterNames.includes(parameter.name))) {
|
|
1562
|
-
throw new PipelineLogicError(spaceTrim((block) => `
|
|
1605
|
+
throw new PipelineLogicError(spaceTrim$1((block) => `
|
|
1563
1606
|
Parameter \`{${parameter.name}}\` is created but not used
|
|
1564
1607
|
|
|
1565
1608
|
You can declare {${parameter.name}} as output parameter by adding in the header:
|
|
@@ -1571,7 +1614,7 @@ function validatePipeline_InnerFunction(pipeline) {
|
|
|
1571
1614
|
}
|
|
1572
1615
|
// Note: Testing that parameter is either input or result of some task
|
|
1573
1616
|
if (!parameter.isInput && !pipeline.tasks.some((task) => task.resultingParameterName === parameter.name)) {
|
|
1574
|
-
throw new PipelineLogicError(spaceTrim((block) => `
|
|
1617
|
+
throw new PipelineLogicError(spaceTrim$1((block) => `
|
|
1575
1618
|
Parameter \`{${parameter.name}}\` is declared but not defined
|
|
1576
1619
|
|
|
1577
1620
|
You can do one of these:
|
|
@@ -1587,14 +1630,14 @@ function validatePipeline_InnerFunction(pipeline) {
|
|
|
1587
1630
|
// Note: Checking each task individually
|
|
1588
1631
|
for (const task of pipeline.tasks) {
|
|
1589
1632
|
if (definedParameters.has(task.resultingParameterName)) {
|
|
1590
|
-
throw new PipelineLogicError(spaceTrim((block) => `
|
|
1633
|
+
throw new PipelineLogicError(spaceTrim$1((block) => `
|
|
1591
1634
|
Parameter \`{${task.resultingParameterName}}\` is defined multiple times
|
|
1592
1635
|
|
|
1593
1636
|
${block(pipelineIdentification)}
|
|
1594
1637
|
`));
|
|
1595
1638
|
}
|
|
1596
1639
|
if (RESERVED_PARAMETER_NAMES.includes(task.resultingParameterName)) {
|
|
1597
|
-
throw new PipelineLogicError(spaceTrim((block) => `
|
|
1640
|
+
throw new PipelineLogicError(spaceTrim$1((block) => `
|
|
1598
1641
|
Parameter name {${task.resultingParameterName}} is reserved, please use different name
|
|
1599
1642
|
|
|
1600
1643
|
${block(pipelineIdentification)}
|
|
@@ -1604,7 +1647,7 @@ function validatePipeline_InnerFunction(pipeline) {
|
|
|
1604
1647
|
if (task.jokerParameterNames && task.jokerParameterNames.length > 0) {
|
|
1605
1648
|
if (!task.format &&
|
|
1606
1649
|
!task.expectations /* <- TODO: Require at least 1 -> min <- expectation to use jokers */) {
|
|
1607
|
-
throw new PipelineLogicError(spaceTrim((block) => `
|
|
1650
|
+
throw new PipelineLogicError(spaceTrim$1((block) => `
|
|
1608
1651
|
Joker parameters are used for {${task.resultingParameterName}} but no expectations are defined
|
|
1609
1652
|
|
|
1610
1653
|
${block(pipelineIdentification)}
|
|
@@ -1612,7 +1655,7 @@ function validatePipeline_InnerFunction(pipeline) {
|
|
|
1612
1655
|
}
|
|
1613
1656
|
for (const joker of task.jokerParameterNames) {
|
|
1614
1657
|
if (!task.dependentParameterNames.includes(joker)) {
|
|
1615
|
-
throw new PipelineLogicError(spaceTrim((block) => `
|
|
1658
|
+
throw new PipelineLogicError(spaceTrim$1((block) => `
|
|
1616
1659
|
Parameter \`{${joker}}\` is used for {${task.resultingParameterName}} as joker but not in \`dependentParameterNames\`
|
|
1617
1660
|
|
|
1618
1661
|
${block(pipelineIdentification)}
|
|
@@ -1623,21 +1666,21 @@ function validatePipeline_InnerFunction(pipeline) {
|
|
|
1623
1666
|
if (task.expectations) {
|
|
1624
1667
|
for (const [unit, { min, max }] of Object.entries(task.expectations)) {
|
|
1625
1668
|
if (min !== undefined && max !== undefined && min > max) {
|
|
1626
|
-
throw new PipelineLogicError(spaceTrim((block) => `
|
|
1669
|
+
throw new PipelineLogicError(spaceTrim$1((block) => `
|
|
1627
1670
|
Min expectation (=${min}) of ${unit} is higher than max expectation (=${max})
|
|
1628
1671
|
|
|
1629
1672
|
${block(pipelineIdentification)}
|
|
1630
1673
|
`));
|
|
1631
1674
|
}
|
|
1632
1675
|
if (min !== undefined && min < 0) {
|
|
1633
|
-
throw new PipelineLogicError(spaceTrim((block) => `
|
|
1676
|
+
throw new PipelineLogicError(spaceTrim$1((block) => `
|
|
1634
1677
|
Min expectation of ${unit} must be zero or positive
|
|
1635
1678
|
|
|
1636
1679
|
${block(pipelineIdentification)}
|
|
1637
1680
|
`));
|
|
1638
1681
|
}
|
|
1639
1682
|
if (max !== undefined && max <= 0) {
|
|
1640
|
-
throw new PipelineLogicError(spaceTrim((block) => `
|
|
1683
|
+
throw new PipelineLogicError(spaceTrim$1((block) => `
|
|
1641
1684
|
Max expectation of ${unit} must be positive
|
|
1642
1685
|
|
|
1643
1686
|
${block(pipelineIdentification)}
|
|
@@ -1659,7 +1702,7 @@ function validatePipeline_InnerFunction(pipeline) {
|
|
|
1659
1702
|
while (unresovedTasks.length > 0) {
|
|
1660
1703
|
if (loopLimit-- < 0) {
|
|
1661
1704
|
// Note: Really UnexpectedError not LimitReachedError - this should not happen and be caught below
|
|
1662
|
-
throw new UnexpectedError(spaceTrim((block) => `
|
|
1705
|
+
throw new UnexpectedError(spaceTrim$1((block) => `
|
|
1663
1706
|
Loop limit reached during detection of circular dependencies in \`validatePipeline\`
|
|
1664
1707
|
|
|
1665
1708
|
${block(pipelineIdentification)}
|
|
@@ -1669,7 +1712,7 @@ function validatePipeline_InnerFunction(pipeline) {
|
|
|
1669
1712
|
if (currentlyResovedTasks.length === 0) {
|
|
1670
1713
|
throw new PipelineLogicError(
|
|
1671
1714
|
// TODO: [๐] DRY
|
|
1672
|
-
spaceTrim((block) => `
|
|
1715
|
+
spaceTrim$1((block) => `
|
|
1673
1716
|
|
|
1674
1717
|
Can not resolve some parameters:
|
|
1675
1718
|
Either you are using a parameter that is not defined, or there are some circular dependencies.
|
|
@@ -1744,7 +1787,7 @@ function isPipelinePrepared(pipeline) {
|
|
|
1744
1787
|
if (pipeline.title === undefined || pipeline.title === '' || pipeline.title === DEFAULT_BOOK_TITLE) {
|
|
1745
1788
|
return false;
|
|
1746
1789
|
}
|
|
1747
|
-
if (!pipeline.personas.every((persona) => persona.
|
|
1790
|
+
if (!pipeline.personas.every((persona) => persona.modelsRequirements !== undefined)) {
|
|
1748
1791
|
return false;
|
|
1749
1792
|
}
|
|
1750
1793
|
if (!pipeline.knowledgeSources.every((knowledgeSource) => knowledgeSource.preparationIds !== undefined)) {
|
|
@@ -1771,6 +1814,9 @@ function isPipelinePrepared(pipeline) {
|
|
|
1771
1814
|
/**
|
|
1772
1815
|
* Function isValidJsonString will tell you if the string is valid JSON or not
|
|
1773
1816
|
*
|
|
1817
|
+
* @param value The string to check
|
|
1818
|
+
* @returns True if the string is a valid JSON string, false otherwise
|
|
1819
|
+
*
|
|
1774
1820
|
* @public exported from `@promptbook/utils`
|
|
1775
1821
|
*/
|
|
1776
1822
|
function isValidJsonString(value /* <- [๐จโโ๏ธ] */) {
|
|
@@ -1779,9 +1825,7 @@ function isValidJsonString(value /* <- [๐จโโ๏ธ] */) {
|
|
|
1779
1825
|
return true;
|
|
1780
1826
|
}
|
|
1781
1827
|
catch (error) {
|
|
1782
|
-
|
|
1783
|
-
throw error;
|
|
1784
|
-
}
|
|
1828
|
+
assertsError(error);
|
|
1785
1829
|
if (error.message.includes('Unexpected token')) {
|
|
1786
1830
|
return false;
|
|
1787
1831
|
}
|
|
@@ -1789,6 +1833,45 @@ function isValidJsonString(value /* <- [๐จโโ๏ธ] */) {
|
|
|
1789
1833
|
}
|
|
1790
1834
|
}
|
|
1791
1835
|
|
|
1836
|
+
/**
|
|
1837
|
+
* Converts a JavaScript Object Notation (JSON) string into an object.
|
|
1838
|
+
*
|
|
1839
|
+
* Note: This is wrapper around `JSON.parse()` with better error and type handling
|
|
1840
|
+
*
|
|
1841
|
+
* @public exported from `@promptbook/utils`
|
|
1842
|
+
*/
|
|
1843
|
+
function jsonParse(value) {
|
|
1844
|
+
if (value === undefined) {
|
|
1845
|
+
throw new Error(`Can not parse JSON from undefined value.`);
|
|
1846
|
+
}
|
|
1847
|
+
else if (typeof value !== 'string') {
|
|
1848
|
+
console.error('Can not parse JSON from non-string value.', { text: value });
|
|
1849
|
+
throw new Error(spaceTrim(`
|
|
1850
|
+
Can not parse JSON from non-string value.
|
|
1851
|
+
|
|
1852
|
+
The value type: ${typeof value}
|
|
1853
|
+
See more in console.
|
|
1854
|
+
`));
|
|
1855
|
+
}
|
|
1856
|
+
try {
|
|
1857
|
+
return JSON.parse(value);
|
|
1858
|
+
}
|
|
1859
|
+
catch (error) {
|
|
1860
|
+
if (!(error instanceof Error)) {
|
|
1861
|
+
throw error;
|
|
1862
|
+
}
|
|
1863
|
+
throw new Error(spaceTrim((block) => `
|
|
1864
|
+
${block(error.message)}
|
|
1865
|
+
|
|
1866
|
+
The JSON text:
|
|
1867
|
+
${block(value)}
|
|
1868
|
+
`));
|
|
1869
|
+
}
|
|
1870
|
+
}
|
|
1871
|
+
/**
|
|
1872
|
+
* TODO: !!!! Use in Promptbook.studio
|
|
1873
|
+
*/
|
|
1874
|
+
|
|
1792
1875
|
/**
|
|
1793
1876
|
* Recursively converts JSON strings to JSON objects
|
|
1794
1877
|
|
|
@@ -1807,7 +1890,7 @@ function jsonStringsToJsons(object) {
|
|
|
1807
1890
|
const newObject = { ...object };
|
|
1808
1891
|
for (const [key, value] of Object.entries(object)) {
|
|
1809
1892
|
if (typeof value === 'string' && isValidJsonString(value)) {
|
|
1810
|
-
newObject[key] =
|
|
1893
|
+
newObject[key] = jsonParse(value);
|
|
1811
1894
|
}
|
|
1812
1895
|
else {
|
|
1813
1896
|
newObject[key] = jsonStringsToJsons(value);
|
|
@@ -1833,7 +1916,7 @@ function deserializeError(error) {
|
|
|
1833
1916
|
message = `${name}: ${message}`;
|
|
1834
1917
|
}
|
|
1835
1918
|
if (stack !== undefined && stack !== '') {
|
|
1836
|
-
message = spaceTrim
|
|
1919
|
+
message = spaceTrim((block) => `
|
|
1837
1920
|
${block(message)}
|
|
1838
1921
|
|
|
1839
1922
|
Original stack trace:
|
|
@@ -1870,11 +1953,11 @@ function assertsTaskSuccessful(executionResult) {
|
|
|
1870
1953
|
throw deserializeError(errors[0]);
|
|
1871
1954
|
}
|
|
1872
1955
|
else {
|
|
1873
|
-
throw new PipelineExecutionError(spaceTrim((block) => `
|
|
1956
|
+
throw new PipelineExecutionError(spaceTrim$1((block) => `
|
|
1874
1957
|
Multiple errors occurred during Promptbook execution
|
|
1875
1958
|
|
|
1876
1959
|
${block(errors
|
|
1877
|
-
.map(({ name, stack, message }, index) => spaceTrim((block) => `
|
|
1960
|
+
.map(({ name, stack, message }, index) => spaceTrim$1((block) => `
|
|
1878
1961
|
${name} ${index + 1}:
|
|
1879
1962
|
${block(stack || message)}
|
|
1880
1963
|
`))
|
|
@@ -1919,8 +2002,8 @@ function createTask(options) {
|
|
|
1919
2002
|
updatedAt = new Date();
|
|
1920
2003
|
errors.push(...executionResult.errors);
|
|
1921
2004
|
warnings.push(...executionResult.warnings);
|
|
1922
|
-
// <- TODO:
|
|
1923
|
-
// TODO: [๐ง ]
|
|
2005
|
+
// <- TODO: [๐] Only unique errors and warnings should be added (or filtered)
|
|
2006
|
+
// TODO: [๐ง ] !! errors, warning, isSuccessful are redundant both in `ExecutionTask` and `ExecutionTask.currentValue`
|
|
1924
2007
|
// Also maybe move `ExecutionTask.currentValue.usage` -> `ExecutionTask.usage`
|
|
1925
2008
|
// And delete `ExecutionTask.currentValue.preparedPipeline`
|
|
1926
2009
|
assertsTaskSuccessful(executionResult);
|
|
@@ -1930,6 +2013,7 @@ function createTask(options) {
|
|
|
1930
2013
|
partialResultSubject.next(executionResult);
|
|
1931
2014
|
}
|
|
1932
2015
|
catch (error) {
|
|
2016
|
+
assertsError(error);
|
|
1933
2017
|
status = 'ERROR';
|
|
1934
2018
|
errors.push(error);
|
|
1935
2019
|
partialResultSubject.error(error);
|
|
@@ -1983,7 +2067,7 @@ function createTask(options) {
|
|
|
1983
2067
|
* TODO: [๐] Split into more files and make `PrepareTask` & `RemoteTask` + split the function
|
|
1984
2068
|
*/
|
|
1985
2069
|
|
|
1986
|
-
var PipelineCollection = [{title:"Prepare Knowledge from Markdown",pipelineUrl:"https://promptbook.studio/promptbook/prepare-knowledge-from-markdown.book",formfactorName:"GENERIC",parameters:[{name:"knowledgeContent",description:"Markdown document content",isInput:true,isOutput:false},{name:"knowledgePieces",description:"The knowledge JSON object",isInput:false,isOutput:true}],tasks:[{taskType:"PROMPT_TASK",name:"knowledge",title:"Knowledge",content:"You are experienced data researcher, extract the important knowledge from the document.\n\n# Rules\n\n- Make pieces of information concise, clear, and easy to understand\n- One piece of information should be approximately 1 paragraph\n- Divide the paragraphs by markdown horizontal lines ---\n- Omit irrelevant information\n- Group redundant information\n- Write just extracted information, nothing else\n\n# The document\n\nTake information from this document:\n\n> {knowledgeContent}",resultingParameterName:"knowledgePieces",dependentParameterNames:["knowledgeContent"]}],personas:[],preparations:[],knowledgeSources:[],knowledgePieces:[],sources:[{type:"BOOK",path:null,content:"# Prepare Knowledge from Markdown\n\n- PIPELINE URL `https://promptbook.studio/promptbook/prepare-knowledge-from-markdown.book`\n- INPUT PARAMETER `{knowledgeContent}` Markdown document content\n- OUTPUT PARAMETER `{knowledgePieces}` The knowledge JSON object\n\n## Knowledge\n\n<!-- TODO: [๐] -FORMAT JSON -->\n\n```markdown\nYou are experienced data researcher, extract the important knowledge from the document.\n\n# Rules\n\n- Make pieces of information concise, clear, and easy to understand\n- One piece of information should be approximately 1 paragraph\n- Divide the paragraphs by markdown horizontal lines ---\n- Omit irrelevant information\n- Group redundant information\n- Write just extracted information, nothing else\n\n# The document\n\nTake information from this document:\n\n> {knowledgeContent}\n```\n\n`-> {knowledgePieces}`\n"}],sourceFile:"./books/prepare-knowledge-from-markdown.book"},{title:"Prepare Keywords",pipelineUrl:"https://promptbook.studio/promptbook/prepare-knowledge-keywords.book",formfactorName:"GENERIC",parameters:[{name:"knowledgePieceContent",description:"The content",isInput:true,isOutput:false},{name:"keywords",description:"Keywords separated by comma",isInput:false,isOutput:true}],tasks:[{taskType:"PROMPT_TASK",name:"knowledge",title:"Knowledge",content:"You are experienced data researcher, detect the important keywords in the document.\n\n# Rules\n\n- Write just keywords separated by comma\n\n# The document\n\nTake information from this document:\n\n> {knowledgePieceContent}",resultingParameterName:"keywords",dependentParameterNames:["knowledgePieceContent"]}],personas:[],preparations:[],knowledgeSources:[],knowledgePieces:[],sources:[{type:"BOOK",path:null,content:"# Prepare Keywords\n\n- PIPELINE URL `https://promptbook.studio/promptbook/prepare-knowledge-keywords.book`\n- INPUT PARAMETER `{knowledgePieceContent}` The content\n- OUTPUT PARAMETER `{keywords}` Keywords separated by comma\n\n## Knowledge\n\n<!-- TODO: [๐] -FORMAT JSON -->\n\n```markdown\nYou are experienced data researcher, detect the important keywords in the document.\n\n# Rules\n\n- Write just keywords separated by comma\n\n# The document\n\nTake information from this document:\n\n> {knowledgePieceContent}\n```\n\n`-> {keywords}`\n"}],sourceFile:"./books/prepare-knowledge-keywords.book"},{title:"Prepare Knowledge-piece Title",pipelineUrl:"https://promptbook.studio/promptbook/prepare-knowledge-title.book",formfactorName:"GENERIC",parameters:[{name:"knowledgePieceContent",description:"The content",isInput:true,isOutput:false},{name:"title",description:"The title of the document",isInput:false,isOutput:true}],tasks:[{taskType:"PROMPT_TASK",name:"knowledge",title:"Knowledge",content:"You are experienced content creator, write best title for the document.\n\n# Rules\n\n- Write just title, nothing else\n- Write maximum 5 words for the title\n\n# The document\n\n> {knowledgePieceContent}",resultingParameterName:"title",expectations:{words:{min:1,max:8}},dependentParameterNames:["knowledgePieceContent"]}],personas:[],preparations:[],knowledgeSources:[],knowledgePieces:[],sources:[{type:"BOOK",path:null,content:"# Prepare Knowledge-piece Title\n\n- PIPELINE URL `https://promptbook.studio/promptbook/prepare-knowledge-title.book`\n- INPUT PARAMETER `{knowledgePieceContent}` The content\n- OUTPUT PARAMETER `{title}` The title of the document\n\n## Knowledge\n\n- EXPECT MIN 1 WORD\n- EXPECT MAX 8 WORDS\n\n```markdown\nYou are experienced content creator, write best title for the document.\n\n# Rules\n\n- Write just title, nothing else\n- Write maximum 5 words for the title\n\n# The document\n\n> {knowledgePieceContent}\n```\n\n`-> {title}`\n"}],sourceFile:"./books/prepare-knowledge-title.book"},{title:"Prepare Persona",pipelineUrl:"https://promptbook.studio/promptbook/prepare-persona.book",formfactorName:"GENERIC",parameters:[{name:"availableModelNames",description:"List of available model names separated by comma (,)",isInput:true,isOutput:false},{name:"personaDescription",description:"Description of the persona",isInput:true,isOutput:false},{name:"modelRequirements",description:"Specific requirements for the model",isInput:false,isOutput:true}],tasks:[{taskType:"PROMPT_TASK",name:"make-model-requirements",title:"Make modelRequirements",content:"You are experienced AI engineer, you need to create virtual assistant.\nWrite\n\n## Example\n\n```json\n{\n\"modelName\": \"gpt-4o\",\n\"systemMessage\": \"You are experienced AI engineer and helpfull assistant.\",\n\"temperature\": 0.7\n}\n```\n\n## Instructions\n\n- Your output format is JSON object\n- Write just the JSON object, no other text should be present\n- It contains the following keys:\n - `modelName`: The name of the model to use\n - `systemMessage`: The system message to provide context to the model\n - `temperature`: The sampling temperature to use\n\n### Key `modelName`\n\nPick from the following models:\n\n- {availableModelNames}\n\n### Key `systemMessage`\n\nThe system message is used to communicate instructions or provide context to the model at the beginning of a conversation. It is displayed in a different format compared to user messages, helping the model understand its role in the conversation. The system message typically guides the model's behavior, sets the tone, or specifies desired output from the model. By utilizing the system message effectively, users can steer the model towards generating more accurate and relevant responses.\n\nFor example:\n\n> You are an experienced AI engineer and helpful assistant.\n\n> You are a friendly and knowledgeable chatbot.\n\n### Key `temperature`\n\nThe sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, the model will use log probability to automatically increase the temperature until certain thresholds are hit.\n\nYou can pick a value between 0 and 2. For example:\n\n- `0.1`: Low temperature, extremely conservative and deterministic\n- `0.5`: Medium temperature, balanced between conservative and creative\n- `1.0`: High temperature, creative and bit random\n- `1.5`: Very high temperature, extremely creative and often chaotic and unpredictable\n- `2.0`: Maximum temperature, completely random and unpredictable, for some extreme creative use cases\n\n# The assistant\n\nTake this description of the persona:\n\n> {personaDescription}",resultingParameterName:"modelRequirements",format:"JSON",dependentParameterNames:["availableModelNames","personaDescription"]}],personas:[],preparations:[],knowledgeSources:[],knowledgePieces:[],sources:[{type:"BOOK",path:null,content:"# Prepare Persona\n\n- PIPELINE URL `https://promptbook.studio/promptbook/prepare-persona.book`\n- INPUT PARAMETER `{availableModelNames}` List of available model names separated by comma (,)\n- INPUT PARAMETER `{personaDescription}` Description of the persona\n- OUTPUT PARAMETER `{modelRequirements}` Specific requirements for the model\n\n## Make modelRequirements\n\n- FORMAT JSON\n\n```markdown\nYou are experienced AI engineer, you need to create virtual assistant.\nWrite\n\n## Example\n\n\\`\\`\\`json\n{\n\"modelName\": \"gpt-4o\",\n\"systemMessage\": \"You are experienced AI engineer and helpfull assistant.\",\n\"temperature\": 0.7\n}\n\\`\\`\\`\n\n## Instructions\n\n- Your output format is JSON object\n- Write just the JSON object, no other text should be present\n- It contains the following keys:\n - `modelName`: The name of the model to use\n - `systemMessage`: The system message to provide context to the model\n - `temperature`: The sampling temperature to use\n\n### Key `modelName`\n\nPick from the following models:\n\n- {availableModelNames}\n\n### Key `systemMessage`\n\nThe system message is used to communicate instructions or provide context to the model at the beginning of a conversation. It is displayed in a different format compared to user messages, helping the model understand its role in the conversation. The system message typically guides the model's behavior, sets the tone, or specifies desired output from the model. By utilizing the system message effectively, users can steer the model towards generating more accurate and relevant responses.\n\nFor example:\n\n> You are an experienced AI engineer and helpful assistant.\n\n> You are a friendly and knowledgeable chatbot.\n\n### Key `temperature`\n\nThe sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, the model will use log probability to automatically increase the temperature until certain thresholds are hit.\n\nYou can pick a value between 0 and 2. For example:\n\n- `0.1`: Low temperature, extremely conservative and deterministic\n- `0.5`: Medium temperature, balanced between conservative and creative\n- `1.0`: High temperature, creative and bit random\n- `1.5`: Very high temperature, extremely creative and often chaotic and unpredictable\n- `2.0`: Maximum temperature, completely random and unpredictable, for some extreme creative use cases\n\n# The assistant\n\nTake this description of the persona:\n\n> {personaDescription}\n```\n\n`-> {modelRequirements}`\n"}],sourceFile:"./books/prepare-persona.book"},{title:"Prepare Title",pipelineUrl:"https://promptbook.studio/promptbook/prepare-title.book",formfactorName:"GENERIC",parameters:[{name:"book",description:"The book to prepare the title for",isInput:true,isOutput:false},{name:"title",description:"Best title for the book",isInput:false,isOutput:true}],tasks:[{taskType:"PROMPT_TASK",name:"make-title",title:"Make title",content:"Make best title for given text which describes the workflow:\n\n## Rules\n\n- Write just title, nothing else\n- Title should be concise and clear - Write maximum ideally 2 words, maximum 5 words\n- Title starts with emoticon\n- Title should not mention the input and output of the workflow but the main purpose of the workflow\n _For example, not \"โ Convert Knowledge-piece to title\" but \"โ Title\"_\n\n## The workflow\n\n> {book}",resultingParameterName:"title",expectations:{words:{min:1,max:8},lines:{min:1,max:1}},dependentParameterNames:["book"]}],personas:[],preparations:[],knowledgeSources:[],knowledgePieces:[],sources:[{type:"BOOK",path:null,content:"# Prepare Title\n\n- PIPELINE URL `https://promptbook.studio/promptbook/prepare-title.book`\n- INPUT PARAMETER `{book}` The book to prepare the title for\n- OUTPUT PARAMETER `{title}` Best title for the book\n\n## Make title\n\n- EXPECT MIN 1 Word\n- EXPECT MAX 8 Words\n- EXPECT EXACTLY 1 Line\n\n```markdown\nMake best title for given text which describes the workflow:\n\n## Rules\n\n- Write just title, nothing else\n- Title should be concise and clear - Write maximum ideally 2 words, maximum 5 words\n- Title starts with emoticon\n- Title should not mention the input and output of the workflow but the main purpose of the workflow\n _For example, not \"โ Convert Knowledge-piece to title\" but \"โ Title\"_\n\n## The workflow\n\n> {book}\n```\n\n`-> {title}`\n"}],sourceFile:"./books/prepare-title.book"}];
|
|
2070
|
+
var PipelineCollection = [{title:"Prepare Knowledge from Markdown",pipelineUrl:"https://promptbook.studio/promptbook/prepare-knowledge-from-markdown.book",formfactorName:"GENERIC",parameters:[{name:"knowledgeContent",description:"Markdown document content",isInput:true,isOutput:false},{name:"knowledgePieces",description:"The knowledge JSON object",isInput:false,isOutput:true}],tasks:[{taskType:"PROMPT_TASK",name:"knowledge",title:"Knowledge",content:"You are experienced data researcher, extract the important knowledge from the document.\n\n# Rules\n\n- Make pieces of information concise, clear, and easy to understand\n- One piece of information should be approximately 1 paragraph\n- Divide the paragraphs by markdown horizontal lines ---\n- Omit irrelevant information\n- Group redundant information\n- Write just extracted information, nothing else\n\n# The document\n\nTake information from this document:\n\n> {knowledgeContent}",resultingParameterName:"knowledgePieces",dependentParameterNames:["knowledgeContent"]}],personas:[],preparations:[],knowledgeSources:[],knowledgePieces:[],sources:[{type:"BOOK",path:null,content:"# Prepare Knowledge from Markdown\n\n- PIPELINE URL `https://promptbook.studio/promptbook/prepare-knowledge-from-markdown.book`\n- INPUT PARAMETER `{knowledgeContent}` Markdown document content\n- OUTPUT PARAMETER `{knowledgePieces}` The knowledge JSON object\n\n## Knowledge\n\n<!-- TODO: [๐] -FORMAT JSON -->\n\n```markdown\nYou are experienced data researcher, extract the important knowledge from the document.\n\n# Rules\n\n- Make pieces of information concise, clear, and easy to understand\n- One piece of information should be approximately 1 paragraph\n- Divide the paragraphs by markdown horizontal lines ---\n- Omit irrelevant information\n- Group redundant information\n- Write just extracted information, nothing else\n\n# The document\n\nTake information from this document:\n\n> {knowledgeContent}\n```\n\n`-> {knowledgePieces}`\n"}],sourceFile:"./books/prepare-knowledge-from-markdown.book"},{title:"Prepare Keywords",pipelineUrl:"https://promptbook.studio/promptbook/prepare-knowledge-keywords.book",formfactorName:"GENERIC",parameters:[{name:"knowledgePieceContent",description:"The content",isInput:true,isOutput:false},{name:"keywords",description:"Keywords separated by comma",isInput:false,isOutput:true}],tasks:[{taskType:"PROMPT_TASK",name:"knowledge",title:"Knowledge",content:"You are experienced data researcher, detect the important keywords in the document.\n\n# Rules\n\n- Write just keywords separated by comma\n\n# The document\n\nTake information from this document:\n\n> {knowledgePieceContent}",resultingParameterName:"keywords",dependentParameterNames:["knowledgePieceContent"]}],personas:[],preparations:[],knowledgeSources:[],knowledgePieces:[],sources:[{type:"BOOK",path:null,content:"# Prepare Keywords\n\n- PIPELINE URL `https://promptbook.studio/promptbook/prepare-knowledge-keywords.book`\n- INPUT PARAMETER `{knowledgePieceContent}` The content\n- OUTPUT PARAMETER `{keywords}` Keywords separated by comma\n\n## Knowledge\n\n<!-- TODO: [๐] -FORMAT JSON -->\n\n```markdown\nYou are experienced data researcher, detect the important keywords in the document.\n\n# Rules\n\n- Write just keywords separated by comma\n\n# The document\n\nTake information from this document:\n\n> {knowledgePieceContent}\n```\n\n`-> {keywords}`\n"}],sourceFile:"./books/prepare-knowledge-keywords.book"},{title:"Prepare Knowledge-piece Title",pipelineUrl:"https://promptbook.studio/promptbook/prepare-knowledge-title.book",formfactorName:"GENERIC",parameters:[{name:"knowledgePieceContent",description:"The content",isInput:true,isOutput:false},{name:"title",description:"The title of the document",isInput:false,isOutput:true}],tasks:[{taskType:"PROMPT_TASK",name:"knowledge",title:"Knowledge",content:"You are experienced content creator, write best title for the document.\n\n# Rules\n\n- Write just title, nothing else\n- Write maximum 5 words for the title\n\n# The document\n\n> {knowledgePieceContent}",resultingParameterName:"title",expectations:{words:{min:1,max:8}},dependentParameterNames:["knowledgePieceContent"]}],personas:[],preparations:[],knowledgeSources:[],knowledgePieces:[],sources:[{type:"BOOK",path:null,content:"# Prepare Knowledge-piece Title\n\n- PIPELINE URL `https://promptbook.studio/promptbook/prepare-knowledge-title.book`\n- INPUT PARAMETER `{knowledgePieceContent}` The content\n- OUTPUT PARAMETER `{title}` The title of the document\n\n## Knowledge\n\n- EXPECT MIN 1 WORD\n- EXPECT MAX 8 WORDS\n\n```markdown\nYou are experienced content creator, write best title for the document.\n\n# Rules\n\n- Write just title, nothing else\n- Write maximum 5 words for the title\n\n# The document\n\n> {knowledgePieceContent}\n```\n\n`-> {title}`\n"}],sourceFile:"./books/prepare-knowledge-title.book"},{title:"Prepare Persona",pipelineUrl:"https://promptbook.studio/promptbook/prepare-persona.book",formfactorName:"GENERIC",parameters:[{name:"availableModels",description:"List of available model names together with their descriptions as JSON",isInput:true,isOutput:false},{name:"personaDescription",description:"Description of the persona",isInput:true,isOutput:false},{name:"modelsRequirements",description:"Specific requirements for the model",isInput:false,isOutput:true}],tasks:[{taskType:"PROMPT_TASK",name:"make-model-requirements",title:"Make modelRequirements",content:"You are an experienced AI engineer, you need to find the best models for virtual assistants:\n\n## Example\n\n```json\n[\n {\n \"modelName\": \"gpt-4o\",\n \"systemMessage\": \"You are experienced AI engineer and helpfull assistant.\",\n \"temperature\": 0.7\n },\n {\n \"modelName\": \"claude-3-5-sonnet\",\n \"systemMessage\": \"You are a friendly and knowledgeable chatbot.\",\n \"temperature\": 0.5\n }\n]\n```\n\n## Instructions\n\n- Your output format is JSON array\n- Sort best-fitting models first\n- Omit any models that are not suitable\n- Write just the JSON, no other text should be present\n- Array contain items with following keys:\n - `modelName`: The name of the model to use\n - `systemMessage`: The system message to provide context to the model\n - `temperature`: The sampling temperature to use\n\n### Key `modelName`\n\nHere are the available models:\n\n```json\n{availableModels}\n```\n\n### Key `systemMessage`\n\nThe system message is used to communicate instructions or provide context to the model at the beginning of a conversation. It is displayed in a different format compared to user messages, helping the model understand its role in the conversation. The system message typically guides the model's behavior, sets the tone, or specifies desired output from the model. By utilizing the system message effectively, users can steer the model towards generating more accurate and relevant responses.\n\nFor example:\n\n> You are an experienced AI engineer and helpful assistant.\n\n> You are a friendly and knowledgeable chatbot.\n\n### Key `temperature`\n\nThe sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, the model will use log probability to automatically increase the temperature until certain thresholds are hit.\n\nYou can pick a value between 0 and 2. For example:\n\n- `0.1`: Low temperature, extremely conservative and deterministic\n- `0.5`: Medium temperature, balanced between conservative and creative\n- `1.0`: High temperature, creative and bit random\n- `1.5`: Very high temperature, extremely creative and often chaotic and unpredictable\n- `2.0`: Maximum temperature, completely random and unpredictable, for some extreme creative use cases\n\n# The assistant\n\nTake this description of the persona:\n\n> {personaDescription}",resultingParameterName:"modelsRequirements",format:"JSON",dependentParameterNames:["availableModels","personaDescription"]}],personas:[],preparations:[],knowledgeSources:[],knowledgePieces:[],sources:[{type:"BOOK",path:null,content:"# Prepare Persona\n\n- PIPELINE URL `https://promptbook.studio/promptbook/prepare-persona.book`\n- INPUT PARAMETER `{availableModels}` List of available model names together with their descriptions as JSON\n- INPUT PARAMETER `{personaDescription}` Description of the persona\n- OUTPUT PARAMETER `{modelsRequirements}` Specific requirements for the model\n\n## Make modelRequirements\n\n- FORMAT JSON\n\n```markdown\nYou are an experienced AI engineer, you need to find the best models for virtual assistants:\n\n## Example\n\n\\`\\`\\`json\n[\n {\n \"modelName\": \"gpt-4o\",\n \"systemMessage\": \"You are experienced AI engineer and helpfull assistant.\",\n \"temperature\": 0.7\n },\n {\n \"modelName\": \"claude-3-5-sonnet\",\n \"systemMessage\": \"You are a friendly and knowledgeable chatbot.\",\n \"temperature\": 0.5\n }\n]\n\\`\\`\\`\n\n## Instructions\n\n- Your output format is JSON array\n- Sort best-fitting models first\n- Omit any models that are not suitable\n- Write just the JSON, no other text should be present\n- Array contain items with following keys:\n - `modelName`: The name of the model to use\n - `systemMessage`: The system message to provide context to the model\n - `temperature`: The sampling temperature to use\n\n### Key `modelName`\n\nHere are the available models:\n\n\\`\\`\\`json\n{availableModels}\n\\`\\`\\`\n\n### Key `systemMessage`\n\nThe system message is used to communicate instructions or provide context to the model at the beginning of a conversation. It is displayed in a different format compared to user messages, helping the model understand its role in the conversation. The system message typically guides the model's behavior, sets the tone, or specifies desired output from the model. By utilizing the system message effectively, users can steer the model towards generating more accurate and relevant responses.\n\nFor example:\n\n> You are an experienced AI engineer and helpful assistant.\n\n> You are a friendly and knowledgeable chatbot.\n\n### Key `temperature`\n\nThe sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, the model will use log probability to automatically increase the temperature until certain thresholds are hit.\n\nYou can pick a value between 0 and 2. For example:\n\n- `0.1`: Low temperature, extremely conservative and deterministic\n- `0.5`: Medium temperature, balanced between conservative and creative\n- `1.0`: High temperature, creative and bit random\n- `1.5`: Very high temperature, extremely creative and often chaotic and unpredictable\n- `2.0`: Maximum temperature, completely random and unpredictable, for some extreme creative use cases\n\n# The assistant\n\nTake this description of the persona:\n\n> {personaDescription}\n```\n\n`-> {modelsRequirements}`\n"}],sourceFile:"./books/prepare-persona.book"},{title:"Prepare Title",pipelineUrl:"https://promptbook.studio/promptbook/prepare-title.book",formfactorName:"GENERIC",parameters:[{name:"book",description:"The book to prepare the title for",isInput:true,isOutput:false},{name:"title",description:"Best title for the book",isInput:false,isOutput:true}],tasks:[{taskType:"PROMPT_TASK",name:"make-title",title:"Make title",content:"Make best title for given text which describes the workflow:\n\n## Rules\n\n- Write just title, nothing else\n- Title should be concise and clear - Write maximum ideally 2 words, maximum 5 words\n- Title starts with emoticon\n- Title should not mention the input and output of the workflow but the main purpose of the workflow\n _For example, not \"โ Convert Knowledge-piece to title\" but \"โ Title\"_\n\n## The workflow\n\n> {book}",resultingParameterName:"title",expectations:{words:{min:1,max:8},lines:{min:1,max:1}},dependentParameterNames:["book"]}],personas:[],preparations:[],knowledgeSources:[],knowledgePieces:[],sources:[{type:"BOOK",path:null,content:"# Prepare Title\n\n- PIPELINE URL `https://promptbook.studio/promptbook/prepare-title.book`\n- INPUT PARAMETER `{book}` The book to prepare the title for\n- OUTPUT PARAMETER `{title}` Best title for the book\n\n## Make title\n\n- EXPECT MIN 1 Word\n- EXPECT MAX 8 Words\n- EXPECT EXACTLY 1 Line\n\n```markdown\nMake best title for given text which describes the workflow:\n\n## Rules\n\n- Write just title, nothing else\n- Title should be concise and clear - Write maximum ideally 2 words, maximum 5 words\n- Title starts with emoticon\n- Title should not mention the input and output of the workflow but the main purpose of the workflow\n _For example, not \"โ Convert Knowledge-piece to title\" but \"โ Title\"_\n\n## The workflow\n\n> {book}\n```\n\n`-> {title}`\n"}],sourceFile:"./books/prepare-title.book"}];
|
|
1987
2071
|
|
|
1988
2072
|
/**
|
|
1989
2073
|
* Checks if value is valid email
|
|
@@ -2232,7 +2316,7 @@ function pipelineJsonToString(pipelineJson) {
|
|
|
2232
2316
|
pipelineString += '\n\n';
|
|
2233
2317
|
pipelineString += '```' + contentLanguage;
|
|
2234
2318
|
pipelineString += '\n';
|
|
2235
|
-
pipelineString += spaceTrim
|
|
2319
|
+
pipelineString += spaceTrim(content);
|
|
2236
2320
|
// <- TODO: [main] !!3 Escape
|
|
2237
2321
|
// <- TODO: [๐ง ] Some clear strategy how to spaceTrim the blocks
|
|
2238
2322
|
pipelineString += '\n';
|
|
@@ -2286,7 +2370,7 @@ function extractParameterNames(template) {
|
|
|
2286
2370
|
*/
|
|
2287
2371
|
function unpreparePipeline(pipeline) {
|
|
2288
2372
|
let { personas, knowledgeSources, tasks } = pipeline;
|
|
2289
|
-
personas = personas.map((persona) => ({ ...persona,
|
|
2373
|
+
personas = personas.map((persona) => ({ ...persona, modelsRequirements: undefined, preparationIds: undefined }));
|
|
2290
2374
|
knowledgeSources = knowledgeSources.map((knowledgeSource) => ({ ...knowledgeSource, preparationIds: undefined }));
|
|
2291
2375
|
tasks = tasks.map((task) => {
|
|
2292
2376
|
let { dependentParameterNames } = task;
|
|
@@ -2337,7 +2421,7 @@ class SimplePipelineCollection {
|
|
|
2337
2421
|
for (const pipeline of pipelines) {
|
|
2338
2422
|
// TODO: [๐ ] DRY
|
|
2339
2423
|
if (pipeline.pipelineUrl === undefined) {
|
|
2340
|
-
throw new PipelineUrlError(spaceTrim(`
|
|
2424
|
+
throw new PipelineUrlError(spaceTrim$1(`
|
|
2341
2425
|
Pipeline with name "${pipeline.title}" does not have defined URL
|
|
2342
2426
|
|
|
2343
2427
|
File:
|
|
@@ -2359,7 +2443,7 @@ class SimplePipelineCollection {
|
|
|
2359
2443
|
pipelineJsonToString(unpreparePipeline(pipeline)) !==
|
|
2360
2444
|
pipelineJsonToString(unpreparePipeline(this.collection.get(pipeline.pipelineUrl)))) {
|
|
2361
2445
|
const existing = this.collection.get(pipeline.pipelineUrl);
|
|
2362
|
-
throw new PipelineUrlError(spaceTrim(`
|
|
2446
|
+
throw new PipelineUrlError(spaceTrim$1(`
|
|
2363
2447
|
Pipeline with URL ${pipeline.pipelineUrl} is already in the collection ๐
|
|
2364
2448
|
|
|
2365
2449
|
Conflicting files:
|
|
@@ -2391,13 +2475,13 @@ class SimplePipelineCollection {
|
|
|
2391
2475
|
const pipeline = this.collection.get(url);
|
|
2392
2476
|
if (!pipeline) {
|
|
2393
2477
|
if (this.listPipelines().length === 0) {
|
|
2394
|
-
throw new NotFoundError(spaceTrim(`
|
|
2478
|
+
throw new NotFoundError(spaceTrim$1(`
|
|
2395
2479
|
Pipeline with url "${url}" not found
|
|
2396
2480
|
|
|
2397
2481
|
No pipelines available
|
|
2398
2482
|
`));
|
|
2399
2483
|
}
|
|
2400
|
-
throw new NotFoundError(spaceTrim((block) => `
|
|
2484
|
+
throw new NotFoundError(spaceTrim$1((block) => `
|
|
2401
2485
|
Pipeline with url "${url}" not found
|
|
2402
2486
|
|
|
2403
2487
|
Available pipelines:
|
|
@@ -2740,14 +2824,15 @@ class MultipleLlmExecutionTools {
|
|
|
2740
2824
|
}
|
|
2741
2825
|
}
|
|
2742
2826
|
catch (error) {
|
|
2743
|
-
|
|
2827
|
+
assertsError(error);
|
|
2828
|
+
if (error instanceof UnexpectedError) {
|
|
2744
2829
|
throw error;
|
|
2745
2830
|
}
|
|
2746
2831
|
errors.push({ llmExecutionTools, error });
|
|
2747
2832
|
}
|
|
2748
2833
|
}
|
|
2749
2834
|
if (errors.length === 1) {
|
|
2750
|
-
throw errors[0];
|
|
2835
|
+
throw errors[0].error;
|
|
2751
2836
|
}
|
|
2752
2837
|
else if (errors.length > 1) {
|
|
2753
2838
|
throw new PipelineExecutionError(
|
|
@@ -2755,7 +2840,7 @@ class MultipleLlmExecutionTools {
|
|
|
2755
2840
|
// 1) OpenAI throw PipelineExecutionError: Parameter `{knowledge}` is not defined
|
|
2756
2841
|
// 2) AnthropicClaude throw PipelineExecutionError: Parameter `{knowledge}` is not defined
|
|
2757
2842
|
// 3) ...
|
|
2758
|
-
spaceTrim
|
|
2843
|
+
spaceTrim((block) => `
|
|
2759
2844
|
All execution tools failed:
|
|
2760
2845
|
|
|
2761
2846
|
${block(errors
|
|
@@ -2768,7 +2853,7 @@ class MultipleLlmExecutionTools {
|
|
|
2768
2853
|
throw new PipelineExecutionError(`You have not provided any \`LlmExecutionTools\``);
|
|
2769
2854
|
}
|
|
2770
2855
|
else {
|
|
2771
|
-
throw new PipelineExecutionError(spaceTrim
|
|
2856
|
+
throw new PipelineExecutionError(spaceTrim((block) => `
|
|
2772
2857
|
You have not provided any \`LlmExecutionTools\` that support model variant "${prompt.modelRequirements.modelVariant}"
|
|
2773
2858
|
|
|
2774
2859
|
Available \`LlmExecutionTools\`:
|
|
@@ -2801,7 +2886,7 @@ class MultipleLlmExecutionTools {
|
|
|
2801
2886
|
*/
|
|
2802
2887
|
function joinLlmExecutionTools(...llmExecutionTools) {
|
|
2803
2888
|
if (llmExecutionTools.length === 0) {
|
|
2804
|
-
const warningMessage = spaceTrim
|
|
2889
|
+
const warningMessage = spaceTrim(`
|
|
2805
2890
|
You have not provided any \`LlmExecutionTools\`
|
|
2806
2891
|
This means that you won't be able to execute any prompts that require large language models like GPT-4 or Anthropic's Claude.
|
|
2807
2892
|
|
|
@@ -2873,27 +2958,48 @@ async function preparePersona(personaDescription, tools, options) {
|
|
|
2873
2958
|
pipeline: await collection.getPipelineByUrl('https://promptbook.studio/promptbook/prepare-persona.book'),
|
|
2874
2959
|
tools,
|
|
2875
2960
|
});
|
|
2876
|
-
// TODO: [๐] Make arrayable LLMs -> single LLM DRY
|
|
2877
2961
|
const _llms = arrayableToArray(tools.llm);
|
|
2878
2962
|
const llmTools = _llms.length === 1 ? _llms[0] : joinLlmExecutionTools(..._llms);
|
|
2879
|
-
const availableModels = await llmTools.listModels()
|
|
2880
|
-
const availableModelNames = availableModels
|
|
2963
|
+
const availableModels = (await llmTools.listModels())
|
|
2881
2964
|
.filter(({ modelVariant }) => modelVariant === 'CHAT')
|
|
2882
|
-
.map(({ modelName }) =>
|
|
2883
|
-
|
|
2884
|
-
|
|
2965
|
+
.map(({ modelName, modelDescription }) => ({
|
|
2966
|
+
modelName,
|
|
2967
|
+
modelDescription,
|
|
2968
|
+
// <- Note: `modelTitle` and `modelVariant` is not relevant for this task
|
|
2969
|
+
}));
|
|
2970
|
+
const result = await preparePersonaExecutor({
|
|
2971
|
+
availableModels /* <- Note: Passing as JSON */,
|
|
2972
|
+
personaDescription,
|
|
2973
|
+
}).asPromise();
|
|
2885
2974
|
const { outputParameters } = result;
|
|
2886
|
-
const {
|
|
2887
|
-
|
|
2975
|
+
const { modelsRequirements: modelsRequirementsJson } = outputParameters;
|
|
2976
|
+
let modelsRequirementsUnchecked = jsonParse(modelsRequirementsJson);
|
|
2888
2977
|
if (isVerbose) {
|
|
2889
|
-
console.info(`PERSONA ${personaDescription}`,
|
|
2978
|
+
console.info(`PERSONA ${personaDescription}`, modelsRequirementsUnchecked);
|
|
2890
2979
|
}
|
|
2891
|
-
|
|
2892
|
-
|
|
2980
|
+
if (!Array.isArray(modelsRequirementsUnchecked)) {
|
|
2981
|
+
// <- TODO: Book should have syntax and system to enforce shape of JSON
|
|
2982
|
+
modelsRequirementsUnchecked = [modelsRequirementsUnchecked];
|
|
2983
|
+
/*
|
|
2984
|
+
throw new UnexpectedError(
|
|
2985
|
+
spaceTrim(
|
|
2986
|
+
(block) => `
|
|
2987
|
+
Invalid \`modelsRequirements\`:
|
|
2988
|
+
|
|
2989
|
+
\`\`\`json
|
|
2990
|
+
${block(JSON.stringify(modelsRequirementsUnchecked, null, 4))}
|
|
2991
|
+
\`\`\`
|
|
2992
|
+
`,
|
|
2993
|
+
),
|
|
2994
|
+
);
|
|
2995
|
+
*/
|
|
2996
|
+
}
|
|
2997
|
+
const modelsRequirements = modelsRequirementsUnchecked.map((modelRequirements) => ({
|
|
2893
2998
|
modelVariant: 'CHAT',
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2999
|
+
...modelRequirements,
|
|
3000
|
+
}));
|
|
3001
|
+
return {
|
|
3002
|
+
modelsRequirements,
|
|
2897
3003
|
};
|
|
2898
3004
|
}
|
|
2899
3005
|
/**
|
|
@@ -3092,14 +3198,14 @@ function $registeredScrapersMessage(availableScrapers) {
|
|
|
3092
3198
|
return { ...metadata, isMetadataAviailable, isInstalled, isAvilableInTools };
|
|
3093
3199
|
});
|
|
3094
3200
|
if (metadata.length === 0) {
|
|
3095
|
-
return spaceTrim
|
|
3201
|
+
return spaceTrim(`
|
|
3096
3202
|
**No scrapers are available**
|
|
3097
3203
|
|
|
3098
3204
|
This is a unexpected behavior, you are probably using some broken version of Promptbook
|
|
3099
3205
|
At least there should be available the metadata of the scrapers
|
|
3100
3206
|
`);
|
|
3101
3207
|
}
|
|
3102
|
-
return spaceTrim
|
|
3208
|
+
return spaceTrim((block) => `
|
|
3103
3209
|
Available scrapers are:
|
|
3104
3210
|
${block(metadata
|
|
3105
3211
|
.map(({ packageName, className, isMetadataAviailable, isInstalled, mimeTypes, isAvilableInBrowser, isAvilableInTools, }, i) => {
|
|
@@ -3588,9 +3694,7 @@ const promptbookFetch = async (urlOrRequest, init) => {
|
|
|
3588
3694
|
return await fetch(urlOrRequest, init);
|
|
3589
3695
|
}
|
|
3590
3696
|
catch (error) {
|
|
3591
|
-
|
|
3592
|
-
throw error;
|
|
3593
|
-
}
|
|
3697
|
+
assertsError(error);
|
|
3594
3698
|
let url;
|
|
3595
3699
|
if (typeof urlOrRequest === 'string') {
|
|
3596
3700
|
url = urlOrRequest;
|
|
@@ -3598,7 +3702,7 @@ const promptbookFetch = async (urlOrRequest, init) => {
|
|
|
3598
3702
|
else if (urlOrRequest instanceof Request) {
|
|
3599
3703
|
url = urlOrRequest.url;
|
|
3600
3704
|
}
|
|
3601
|
-
throw new PromptbookFetchError(spaceTrim
|
|
3705
|
+
throw new PromptbookFetchError(spaceTrim((block) => `
|
|
3602
3706
|
Can not fetch "${url}"
|
|
3603
3707
|
|
|
3604
3708
|
Fetch error:
|
|
@@ -3689,7 +3793,7 @@ async function makeKnowledgeSourceHandler(knowledgeSource, tools, options) {
|
|
|
3689
3793
|
const fileExtension = getFileExtension(filename);
|
|
3690
3794
|
const mimeType = extensionToMimeType(fileExtension || '');
|
|
3691
3795
|
if (!(await isFileExisting(filename, tools.fs))) {
|
|
3692
|
-
throw new NotFoundError(spaceTrim
|
|
3796
|
+
throw new NotFoundError(spaceTrim((block) => `
|
|
3693
3797
|
Can not make source handler for file which does not exist:
|
|
3694
3798
|
|
|
3695
3799
|
File:
|
|
@@ -3719,7 +3823,7 @@ async function makeKnowledgeSourceHandler(knowledgeSource, tools, options) {
|
|
|
3719
3823
|
> },
|
|
3720
3824
|
*/
|
|
3721
3825
|
async asJson() {
|
|
3722
|
-
return
|
|
3826
|
+
return jsonParse(await tools.fs.readFile(filename, 'utf-8'));
|
|
3723
3827
|
},
|
|
3724
3828
|
async asText() {
|
|
3725
3829
|
return await tools.fs.readFile(filename, 'utf-8');
|
|
@@ -3776,7 +3880,7 @@ async function prepareKnowledgePieces(knowledgeSources, tools, options) {
|
|
|
3776
3880
|
// <- TODO: [๐ช] Here should be no need for spreading new array, just `partialPieces = partialPiecesUnchecked`
|
|
3777
3881
|
break;
|
|
3778
3882
|
}
|
|
3779
|
-
console.warn(spaceTrim
|
|
3883
|
+
console.warn(spaceTrim((block) => `
|
|
3780
3884
|
Cannot scrape knowledge from source despite the scraper \`${scraper.metadata.className}\` supports the mime type "${sourceHandler.mimeType}".
|
|
3781
3885
|
|
|
3782
3886
|
The source:
|
|
@@ -3792,7 +3896,7 @@ async function prepareKnowledgePieces(knowledgeSources, tools, options) {
|
|
|
3792
3896
|
// <- TODO: [๐ฎ] Some standard way how to transform errors into warnings and how to handle non-critical fails during the tasks
|
|
3793
3897
|
}
|
|
3794
3898
|
if (partialPieces === null) {
|
|
3795
|
-
throw new KnowledgeScrapeError(spaceTrim
|
|
3899
|
+
throw new KnowledgeScrapeError(spaceTrim((block) => `
|
|
3796
3900
|
Cannot scrape knowledge
|
|
3797
3901
|
|
|
3798
3902
|
The source:
|
|
@@ -3821,9 +3925,7 @@ async function prepareKnowledgePieces(knowledgeSources, tools, options) {
|
|
|
3821
3925
|
knowledgePreparedUnflatten[index] = pieces;
|
|
3822
3926
|
}
|
|
3823
3927
|
catch (error) {
|
|
3824
|
-
|
|
3825
|
-
throw error;
|
|
3826
|
-
}
|
|
3928
|
+
assertsError(error);
|
|
3827
3929
|
console.warn(error);
|
|
3828
3930
|
// <- TODO: [๐ฎ] Some standard way how to transform errors into warnings and how to handle non-critical fails during the tasks
|
|
3829
3931
|
}
|
|
@@ -3870,7 +3972,7 @@ async function prepareTasks(pipeline, tools, options) {
|
|
|
3870
3972
|
if (task.taskType === 'PROMPT_TASK' &&
|
|
3871
3973
|
knowledgePiecesCount > 0 &&
|
|
3872
3974
|
!dependentParameterNames.includes('knowledge')) {
|
|
3873
|
-
preparedContent = spaceTrim(`
|
|
3975
|
+
preparedContent = spaceTrim$1(`
|
|
3874
3976
|
{content}
|
|
3875
3977
|
|
|
3876
3978
|
## Knowledge
|
|
@@ -3979,14 +4081,14 @@ async function preparePipeline(pipeline, tools, options) {
|
|
|
3979
4081
|
// TODO: [๐][๐ง ] Implement some `mapAsync` function
|
|
3980
4082
|
const preparedPersonas = new Array(personas.length);
|
|
3981
4083
|
await forEachAsync(personas, { maxParallelCount /* <- TODO: [๐ช] When there are subtasks, this maximul limit can be broken */ }, async (persona, index) => {
|
|
3982
|
-
const
|
|
4084
|
+
const { modelsRequirements } = await preparePersona(persona.description, { ...tools, llm: llmToolsWithUsage }, {
|
|
3983
4085
|
rootDirname,
|
|
3984
4086
|
maxParallelCount /* <- TODO: [๐ช] */,
|
|
3985
4087
|
isVerbose,
|
|
3986
4088
|
});
|
|
3987
4089
|
const preparedPersona = {
|
|
3988
4090
|
...persona,
|
|
3989
|
-
|
|
4091
|
+
modelsRequirements,
|
|
3990
4092
|
preparationIds: [/* TODO: [๐ง] -> */ currentPreparation.id],
|
|
3991
4093
|
// <- TODO: [๐] Make some standard order of json properties
|
|
3992
4094
|
};
|
|
@@ -4115,13 +4217,19 @@ function valueToString(value) {
|
|
|
4115
4217
|
return value.toISOString();
|
|
4116
4218
|
}
|
|
4117
4219
|
else {
|
|
4118
|
-
|
|
4220
|
+
try {
|
|
4221
|
+
return JSON.stringify(value);
|
|
4222
|
+
}
|
|
4223
|
+
catch (error) {
|
|
4224
|
+
if (error instanceof TypeError && error.message.includes('circular structure')) {
|
|
4225
|
+
return VALUE_STRINGS.circular;
|
|
4226
|
+
}
|
|
4227
|
+
throw error;
|
|
4228
|
+
}
|
|
4119
4229
|
}
|
|
4120
4230
|
}
|
|
4121
4231
|
catch (error) {
|
|
4122
|
-
|
|
4123
|
-
throw error;
|
|
4124
|
-
}
|
|
4232
|
+
assertsError(error);
|
|
4125
4233
|
console.error(error);
|
|
4126
4234
|
return VALUE_STRINGS.unserializable;
|
|
4127
4235
|
}
|
|
@@ -4178,10 +4286,8 @@ function extractVariablesFromJavascript(script) {
|
|
|
4178
4286
|
}
|
|
4179
4287
|
}
|
|
4180
4288
|
catch (error) {
|
|
4181
|
-
|
|
4182
|
-
|
|
4183
|
-
}
|
|
4184
|
-
throw new ParseError(spaceTrim((block) => `
|
|
4289
|
+
assertsError(error);
|
|
4290
|
+
throw new ParseError(spaceTrim$1((block) => `
|
|
4185
4291
|
Can not extract variables from the script
|
|
4186
4292
|
${block(error.stack || error.message)}
|
|
4187
4293
|
|
|
@@ -4299,6 +4405,46 @@ const MANDATORY_CSV_SETTINGS = Object.freeze({
|
|
|
4299
4405
|
// encoding: 'utf-8',
|
|
4300
4406
|
});
|
|
4301
4407
|
|
|
4408
|
+
/**
|
|
4409
|
+
* Function to check if a string is valid CSV
|
|
4410
|
+
*
|
|
4411
|
+
* @param value The string to check
|
|
4412
|
+
* @returns True if the string is a valid CSV string, false otherwise
|
|
4413
|
+
*
|
|
4414
|
+
* @public exported from `@promptbook/utils`
|
|
4415
|
+
*/
|
|
4416
|
+
function isValidCsvString(value) {
|
|
4417
|
+
try {
|
|
4418
|
+
// A simple check for CSV format: at least one comma and no invalid characters
|
|
4419
|
+
if (value.includes(',') && /^[\w\s,"']+$/.test(value)) {
|
|
4420
|
+
return true;
|
|
4421
|
+
}
|
|
4422
|
+
return false;
|
|
4423
|
+
}
|
|
4424
|
+
catch (error) {
|
|
4425
|
+
assertsError(error);
|
|
4426
|
+
return false;
|
|
4427
|
+
}
|
|
4428
|
+
}
|
|
4429
|
+
|
|
4430
|
+
/**
|
|
4431
|
+
* Converts a CSV string into an object
|
|
4432
|
+
*
|
|
4433
|
+
* Note: This is wrapper around `papaparse.parse()` with better autohealing
|
|
4434
|
+
*
|
|
4435
|
+
* @private - for now until `@promptbook/csv` is released
|
|
4436
|
+
*/
|
|
4437
|
+
function csvParse(value /* <- TODO: string_csv */, settings, schema /* <- TODO: Make CSV Schemas */) {
|
|
4438
|
+
settings = { ...settings, ...MANDATORY_CSV_SETTINGS };
|
|
4439
|
+
// Note: Autoheal invalid '\n' characters
|
|
4440
|
+
if (settings.newline && !settings.newline.includes('\r') && value.includes('\r')) {
|
|
4441
|
+
console.warn('CSV string contains carriage return characters, but in the CSV settings the `newline` setting does not include them. Autohealing the CSV string.');
|
|
4442
|
+
value = value.replace(/\r\n/g, '\n').replace(/\r/g, '\n');
|
|
4443
|
+
}
|
|
4444
|
+
const csv = parse(value, settings);
|
|
4445
|
+
return csv;
|
|
4446
|
+
}
|
|
4447
|
+
|
|
4302
4448
|
/**
|
|
4303
4449
|
* Definition for CSV spreadsheet
|
|
4304
4450
|
*
|
|
@@ -4309,7 +4455,7 @@ const CsvFormatDefinition = {
|
|
|
4309
4455
|
formatName: 'CSV',
|
|
4310
4456
|
aliases: ['SPREADSHEET', 'TABLE'],
|
|
4311
4457
|
isValid(value, settings, schema) {
|
|
4312
|
-
return
|
|
4458
|
+
return isValidCsvString(value);
|
|
4313
4459
|
},
|
|
4314
4460
|
canBeValid(partialValue, settings, schema) {
|
|
4315
4461
|
return true;
|
|
@@ -4321,10 +4467,9 @@ const CsvFormatDefinition = {
|
|
|
4321
4467
|
{
|
|
4322
4468
|
subvalueName: 'ROW',
|
|
4323
4469
|
async mapValues(value, outputParameterName, settings, mapCallback) {
|
|
4324
|
-
|
|
4325
|
-
const csv = parse(value, { ...settings, ...MANDATORY_CSV_SETTINGS });
|
|
4470
|
+
const csv = csvParse(value, settings);
|
|
4326
4471
|
if (csv.errors.length !== 0) {
|
|
4327
|
-
throw new CsvFormatError(spaceTrim
|
|
4472
|
+
throw new CsvFormatError(spaceTrim((block) => `
|
|
4328
4473
|
CSV parsing error
|
|
4329
4474
|
|
|
4330
4475
|
Error(s) from CSV parsing:
|
|
@@ -4352,10 +4497,9 @@ const CsvFormatDefinition = {
|
|
|
4352
4497
|
{
|
|
4353
4498
|
subvalueName: 'CELL',
|
|
4354
4499
|
async mapValues(value, outputParameterName, settings, mapCallback) {
|
|
4355
|
-
|
|
4356
|
-
const csv = parse(value, { ...settings, ...MANDATORY_CSV_SETTINGS });
|
|
4500
|
+
const csv = csvParse(value, settings);
|
|
4357
4501
|
if (csv.errors.length !== 0) {
|
|
4358
|
-
throw new CsvFormatError(spaceTrim
|
|
4502
|
+
throw new CsvFormatError(spaceTrim((block) => `
|
|
4359
4503
|
CSV parsing error
|
|
4360
4504
|
|
|
4361
4505
|
Error(s) from CSV parsing:
|
|
@@ -4463,6 +4607,30 @@ const TextFormatDefinition = {
|
|
|
4463
4607
|
* TODO: [๐ข] Allow to expect something inside each item of list and other formats
|
|
4464
4608
|
*/
|
|
4465
4609
|
|
|
4610
|
+
/**
|
|
4611
|
+
* Function to check if a string is valid XML
|
|
4612
|
+
*
|
|
4613
|
+
* @param value
|
|
4614
|
+
* @returns True if the string is a valid XML string, false otherwise
|
|
4615
|
+
*
|
|
4616
|
+
* @public exported from `@promptbook/utils`
|
|
4617
|
+
*/
|
|
4618
|
+
function isValidXmlString(value) {
|
|
4619
|
+
try {
|
|
4620
|
+
const parser = new DOMParser();
|
|
4621
|
+
const parsedDocument = parser.parseFromString(value, 'application/xml');
|
|
4622
|
+
const parserError = parsedDocument.getElementsByTagName('parsererror');
|
|
4623
|
+
if (parserError.length > 0) {
|
|
4624
|
+
return false;
|
|
4625
|
+
}
|
|
4626
|
+
return true;
|
|
4627
|
+
}
|
|
4628
|
+
catch (error) {
|
|
4629
|
+
assertsError(error);
|
|
4630
|
+
return false;
|
|
4631
|
+
}
|
|
4632
|
+
}
|
|
4633
|
+
|
|
4466
4634
|
/**
|
|
4467
4635
|
* Definition for XML format
|
|
4468
4636
|
*
|
|
@@ -4472,7 +4640,7 @@ const XmlFormatDefinition = {
|
|
|
4472
4640
|
formatName: 'XML',
|
|
4473
4641
|
mimeType: 'application/xml',
|
|
4474
4642
|
isValid(value, settings, schema) {
|
|
4475
|
-
return
|
|
4643
|
+
return isValidXmlString(value);
|
|
4476
4644
|
},
|
|
4477
4645
|
canBeValid(partialValue, settings, schema) {
|
|
4478
4646
|
return true;
|
|
@@ -4545,7 +4713,7 @@ function mapAvailableToExpectedParameters(options) {
|
|
|
4545
4713
|
}
|
|
4546
4714
|
// Phase 2๏ธโฃ: Non-matching mapping
|
|
4547
4715
|
if (expectedParameterNames.size !== availableParametersNames.size) {
|
|
4548
|
-
throw new PipelineExecutionError(spaceTrim
|
|
4716
|
+
throw new PipelineExecutionError(spaceTrim((block) => `
|
|
4549
4717
|
Can not map available parameters to expected parameters
|
|
4550
4718
|
|
|
4551
4719
|
Mapped parameters:
|
|
@@ -4947,7 +5115,7 @@ async function executeAttempts(options) {
|
|
|
4947
5115
|
const jokerParameterName = jokerParameterNames[jokerParameterNames.length + attempt];
|
|
4948
5116
|
// TODO: [๐ง ][๐ญ] JOKERS, EXPECTATIONS, POSTPROCESSING and FOREACH
|
|
4949
5117
|
if (isJokerAttempt && !jokerParameterName) {
|
|
4950
|
-
throw new UnexpectedError(spaceTrim((block) => `
|
|
5118
|
+
throw new UnexpectedError(spaceTrim$1((block) => `
|
|
4951
5119
|
Joker not found in attempt ${attempt}
|
|
4952
5120
|
|
|
4953
5121
|
${block(pipelineIdentification)}
|
|
@@ -4958,7 +5126,7 @@ async function executeAttempts(options) {
|
|
|
4958
5126
|
$ongoingTaskResult.$expectError = null;
|
|
4959
5127
|
if (isJokerAttempt) {
|
|
4960
5128
|
if (parameters[jokerParameterName] === undefined) {
|
|
4961
|
-
throw new PipelineExecutionError(spaceTrim((block) => `
|
|
5129
|
+
throw new PipelineExecutionError(spaceTrim$1((block) => `
|
|
4962
5130
|
Joker parameter {${jokerParameterName}} not defined
|
|
4963
5131
|
|
|
4964
5132
|
${block(pipelineIdentification)}
|
|
@@ -5016,7 +5184,7 @@ async function executeAttempts(options) {
|
|
|
5016
5184
|
$ongoingTaskResult.$resultString = $ongoingTaskResult.$completionResult.content;
|
|
5017
5185
|
break variant;
|
|
5018
5186
|
case 'EMBEDDING':
|
|
5019
|
-
throw new PipelineExecutionError(spaceTrim((block) => `
|
|
5187
|
+
throw new PipelineExecutionError(spaceTrim$1((block) => `
|
|
5020
5188
|
Embedding model can not be used in pipeline
|
|
5021
5189
|
|
|
5022
5190
|
This should be catched during parsing
|
|
@@ -5027,7 +5195,7 @@ async function executeAttempts(options) {
|
|
|
5027
5195
|
break variant;
|
|
5028
5196
|
// <- case [๐ค]:
|
|
5029
5197
|
default:
|
|
5030
|
-
throw new PipelineExecutionError(spaceTrim((block) => `
|
|
5198
|
+
throw new PipelineExecutionError(spaceTrim$1((block) => `
|
|
5031
5199
|
Unknown model variant "${task.modelRequirements.modelVariant}"
|
|
5032
5200
|
|
|
5033
5201
|
${block(pipelineIdentification)}
|
|
@@ -5038,14 +5206,14 @@ async function executeAttempts(options) {
|
|
|
5038
5206
|
break;
|
|
5039
5207
|
case 'SCRIPT_TASK':
|
|
5040
5208
|
if (arrayableToArray(tools.script).length === 0) {
|
|
5041
|
-
throw new PipelineExecutionError(spaceTrim((block) => `
|
|
5209
|
+
throw new PipelineExecutionError(spaceTrim$1((block) => `
|
|
5042
5210
|
No script execution tools are available
|
|
5043
5211
|
|
|
5044
5212
|
${block(pipelineIdentification)}
|
|
5045
5213
|
`));
|
|
5046
5214
|
}
|
|
5047
5215
|
if (!task.contentLanguage) {
|
|
5048
|
-
throw new PipelineExecutionError(spaceTrim((block) => `
|
|
5216
|
+
throw new PipelineExecutionError(spaceTrim$1((block) => `
|
|
5049
5217
|
Script language is not defined for SCRIPT TASK "${task.name}"
|
|
5050
5218
|
|
|
5051
5219
|
${block(pipelineIdentification)}
|
|
@@ -5062,9 +5230,7 @@ async function executeAttempts(options) {
|
|
|
5062
5230
|
break scripts;
|
|
5063
5231
|
}
|
|
5064
5232
|
catch (error) {
|
|
5065
|
-
|
|
5066
|
-
throw error;
|
|
5067
|
-
}
|
|
5233
|
+
assertsError(error);
|
|
5068
5234
|
if (error instanceof UnexpectedError) {
|
|
5069
5235
|
throw error;
|
|
5070
5236
|
}
|
|
@@ -5078,7 +5244,7 @@ async function executeAttempts(options) {
|
|
|
5078
5244
|
throw $ongoingTaskResult.$scriptPipelineExecutionErrors[0];
|
|
5079
5245
|
}
|
|
5080
5246
|
else {
|
|
5081
|
-
throw new PipelineExecutionError(spaceTrim((block) => `
|
|
5247
|
+
throw new PipelineExecutionError(spaceTrim$1((block) => `
|
|
5082
5248
|
Script execution failed ${$ongoingTaskResult.$scriptPipelineExecutionErrors.length}x
|
|
5083
5249
|
|
|
5084
5250
|
${block(pipelineIdentification)}
|
|
@@ -5092,7 +5258,7 @@ async function executeAttempts(options) {
|
|
|
5092
5258
|
break taskType;
|
|
5093
5259
|
case 'DIALOG_TASK':
|
|
5094
5260
|
if (tools.userInterface === undefined) {
|
|
5095
|
-
throw new PipelineExecutionError(spaceTrim((block) => `
|
|
5261
|
+
throw new PipelineExecutionError(spaceTrim$1((block) => `
|
|
5096
5262
|
User interface tools are not available
|
|
5097
5263
|
|
|
5098
5264
|
${block(pipelineIdentification)}
|
|
@@ -5110,7 +5276,7 @@ async function executeAttempts(options) {
|
|
|
5110
5276
|
break taskType;
|
|
5111
5277
|
// <- case: [๐
ฑ]
|
|
5112
5278
|
default:
|
|
5113
|
-
throw new PipelineExecutionError(spaceTrim((block) => `
|
|
5279
|
+
throw new PipelineExecutionError(spaceTrim$1((block) => `
|
|
5114
5280
|
Unknown execution type "${task.taskType}"
|
|
5115
5281
|
|
|
5116
5282
|
${block(pipelineIdentification)}
|
|
@@ -5134,9 +5300,7 @@ async function executeAttempts(options) {
|
|
|
5134
5300
|
break scripts;
|
|
5135
5301
|
}
|
|
5136
5302
|
catch (error) {
|
|
5137
|
-
|
|
5138
|
-
throw error;
|
|
5139
|
-
}
|
|
5303
|
+
assertsError(error);
|
|
5140
5304
|
if (error instanceof UnexpectedError) {
|
|
5141
5305
|
throw error;
|
|
5142
5306
|
}
|
|
@@ -5159,7 +5323,7 @@ async function executeAttempts(options) {
|
|
|
5159
5323
|
}
|
|
5160
5324
|
catch (error) {
|
|
5161
5325
|
keepUnused(error);
|
|
5162
|
-
throw new ExpectError(spaceTrim((block) => `
|
|
5326
|
+
throw new ExpectError(spaceTrim$1((block) => `
|
|
5163
5327
|
Expected valid JSON string
|
|
5164
5328
|
|
|
5165
5329
|
${block(
|
|
@@ -5169,7 +5333,7 @@ async function executeAttempts(options) {
|
|
|
5169
5333
|
}
|
|
5170
5334
|
}
|
|
5171
5335
|
else {
|
|
5172
|
-
throw new UnexpectedError(spaceTrim((block) => `
|
|
5336
|
+
throw new UnexpectedError(spaceTrim$1((block) => `
|
|
5173
5337
|
Unknown format "${task.format}"
|
|
5174
5338
|
|
|
5175
5339
|
${block(pipelineIdentification)}
|
|
@@ -5209,7 +5373,7 @@ async function executeAttempts(options) {
|
|
|
5209
5373
|
}
|
|
5210
5374
|
}
|
|
5211
5375
|
if ($ongoingTaskResult.$expectError !== null && attempt === maxAttempts - 1) {
|
|
5212
|
-
throw new PipelineExecutionError(spaceTrim((block) => {
|
|
5376
|
+
throw new PipelineExecutionError(spaceTrim$1((block) => {
|
|
5213
5377
|
var _a, _b, _c;
|
|
5214
5378
|
return `
|
|
5215
5379
|
LLM execution failed ${maxExecutionAttempts}x
|
|
@@ -5232,7 +5396,7 @@ async function executeAttempts(options) {
|
|
|
5232
5396
|
Last result:
|
|
5233
5397
|
${block($ongoingTaskResult.$resultString === null
|
|
5234
5398
|
? 'null'
|
|
5235
|
-
: spaceTrim($ongoingTaskResult.$resultString)
|
|
5399
|
+
: spaceTrim$1($ongoingTaskResult.$resultString)
|
|
5236
5400
|
.split('\n')
|
|
5237
5401
|
.map((line) => `> ${line}`)
|
|
5238
5402
|
.join('\n'))}
|
|
@@ -5242,7 +5406,7 @@ async function executeAttempts(options) {
|
|
|
5242
5406
|
}
|
|
5243
5407
|
}
|
|
5244
5408
|
if ($ongoingTaskResult.$resultString === null) {
|
|
5245
|
-
throw new UnexpectedError(spaceTrim((block) => `
|
|
5409
|
+
throw new UnexpectedError(spaceTrim$1((block) => `
|
|
5246
5410
|
Something went wrong and prompt result is null
|
|
5247
5411
|
|
|
5248
5412
|
${block(pipelineIdentification)}
|
|
@@ -5265,7 +5429,7 @@ async function executeFormatSubvalues(options) {
|
|
|
5265
5429
|
return /* not await */ executeAttempts(options);
|
|
5266
5430
|
}
|
|
5267
5431
|
if (jokerParameterNames.length !== 0) {
|
|
5268
|
-
throw new UnexpectedError(spaceTrim
|
|
5432
|
+
throw new UnexpectedError(spaceTrim((block) => `
|
|
5269
5433
|
JOKER parameters are not supported together with FOREACH command
|
|
5270
5434
|
|
|
5271
5435
|
[๐งโโ๏ธ] This should be prevented in \`validatePipeline\`
|
|
@@ -5278,7 +5442,7 @@ async function executeFormatSubvalues(options) {
|
|
|
5278
5442
|
if (formatDefinition === undefined) {
|
|
5279
5443
|
throw new UnexpectedError(
|
|
5280
5444
|
// <- TODO: [๐ง ][๐ง] Should be formats fixed per promptbook version or behave as plugins (=> change UnexpectedError)
|
|
5281
|
-
spaceTrim
|
|
5445
|
+
spaceTrim((block) => `
|
|
5282
5446
|
Unsupported format "${task.foreach.formatName}"
|
|
5283
5447
|
|
|
5284
5448
|
Available formats:
|
|
@@ -5295,7 +5459,7 @@ async function executeFormatSubvalues(options) {
|
|
|
5295
5459
|
if (subvalueDefinition === undefined) {
|
|
5296
5460
|
throw new UnexpectedError(
|
|
5297
5461
|
// <- TODO: [๐ง ][๐ง] Should be formats fixed per promptbook version or behave as plugins (=> change UnexpectedError)
|
|
5298
|
-
spaceTrim
|
|
5462
|
+
spaceTrim((block) => `
|
|
5299
5463
|
Unsupported subformat name "${task.foreach.subformatName}" for format "${task.foreach.formatName}"
|
|
5300
5464
|
|
|
5301
5465
|
Available subformat names for format "${formatDefinition.formatName}":
|
|
@@ -5328,7 +5492,7 @@ async function executeFormatSubvalues(options) {
|
|
|
5328
5492
|
if (!(error instanceof PipelineExecutionError)) {
|
|
5329
5493
|
throw error;
|
|
5330
5494
|
}
|
|
5331
|
-
throw new PipelineExecutionError(spaceTrim
|
|
5495
|
+
throw new PipelineExecutionError(spaceTrim((block) => `
|
|
5332
5496
|
${error.message}
|
|
5333
5497
|
|
|
5334
5498
|
This is error in FOREACH command
|
|
@@ -5348,7 +5512,7 @@ async function executeFormatSubvalues(options) {
|
|
|
5348
5512
|
...options,
|
|
5349
5513
|
priority: priority + index,
|
|
5350
5514
|
parameters: allSubparameters,
|
|
5351
|
-
pipelineIdentification: spaceTrim
|
|
5515
|
+
pipelineIdentification: spaceTrim((block) => `
|
|
5352
5516
|
${block(pipelineIdentification)}
|
|
5353
5517
|
Subparameter index: ${index}
|
|
5354
5518
|
`),
|
|
@@ -5379,13 +5543,79 @@ async function getExamplesForTask(task) {
|
|
|
5379
5543
|
/**
|
|
5380
5544
|
* @@@
|
|
5381
5545
|
*
|
|
5546
|
+
* Here is the place where RAG (retrieval-augmented generation) happens
|
|
5547
|
+
*
|
|
5382
5548
|
* @private internal utility of `createPipelineExecutor`
|
|
5383
5549
|
*/
|
|
5384
5550
|
async function getKnowledgeForTask(options) {
|
|
5385
|
-
const { preparedPipeline, task } = options;
|
|
5386
|
-
|
|
5551
|
+
const { tools, preparedPipeline, task } = options;
|
|
5552
|
+
const firstKnowlegePiece = preparedPipeline.knowledgePieces[0];
|
|
5553
|
+
const firstKnowlegeIndex = firstKnowlegePiece === null || firstKnowlegePiece === void 0 ? void 0 : firstKnowlegePiece.index[0];
|
|
5554
|
+
// <- TODO: Do not use just first knowledge piece and first index to determine embedding model, use also keyword search
|
|
5555
|
+
if (firstKnowlegePiece === undefined || firstKnowlegeIndex === undefined) {
|
|
5556
|
+
return 'No knowledge pieces found';
|
|
5557
|
+
}
|
|
5558
|
+
// TODO: [๐] Make arrayable LLMs -> single LLM DRY
|
|
5559
|
+
const _llms = arrayableToArray(tools.llm);
|
|
5560
|
+
const llmTools = _llms.length === 1 ? _llms[0] : joinLlmExecutionTools(..._llms);
|
|
5561
|
+
const taskEmbeddingPrompt = {
|
|
5562
|
+
title: 'Knowledge Search',
|
|
5563
|
+
modelRequirements: {
|
|
5564
|
+
modelVariant: 'EMBEDDING',
|
|
5565
|
+
modelName: firstKnowlegeIndex.modelName,
|
|
5566
|
+
},
|
|
5567
|
+
content: task.content,
|
|
5568
|
+
parameters: {
|
|
5569
|
+
/* !!!!!!!! */
|
|
5570
|
+
},
|
|
5571
|
+
};
|
|
5572
|
+
const taskEmbeddingResult = await llmTools.callEmbeddingModel(taskEmbeddingPrompt);
|
|
5573
|
+
const knowledgePiecesWithRelevance = preparedPipeline.knowledgePieces.map((knowledgePiece) => {
|
|
5574
|
+
const { index } = knowledgePiece;
|
|
5575
|
+
const knowledgePieceIndex = index.find((i) => i.modelName === firstKnowlegeIndex.modelName);
|
|
5576
|
+
// <- TODO: Do not use just first knowledge piece and first index to determine embedding model
|
|
5577
|
+
if (knowledgePieceIndex === undefined) {
|
|
5578
|
+
return {
|
|
5579
|
+
content: knowledgePiece.content,
|
|
5580
|
+
relevance: 0,
|
|
5581
|
+
};
|
|
5582
|
+
}
|
|
5583
|
+
const relevance = computeCosineSimilarity(knowledgePieceIndex.position, taskEmbeddingResult.content);
|
|
5584
|
+
return {
|
|
5585
|
+
content: knowledgePiece.content,
|
|
5586
|
+
relevance,
|
|
5587
|
+
};
|
|
5588
|
+
});
|
|
5589
|
+
const knowledgePiecesSorted = knowledgePiecesWithRelevance.sort((a, b) => a.relevance - b.relevance);
|
|
5590
|
+
const knowledgePiecesLimited = knowledgePiecesSorted.slice(0, 5);
|
|
5591
|
+
console.log('!!! Embedding', {
|
|
5592
|
+
task,
|
|
5593
|
+
taskEmbeddingPrompt,
|
|
5594
|
+
taskEmbeddingResult,
|
|
5595
|
+
firstKnowlegePiece,
|
|
5596
|
+
firstKnowlegeIndex,
|
|
5597
|
+
knowledgePiecesWithRelevance,
|
|
5598
|
+
knowledgePiecesSorted,
|
|
5599
|
+
knowledgePiecesLimited,
|
|
5600
|
+
});
|
|
5601
|
+
return knowledgePiecesLimited.map(({ content }) => `- ${content}`).join('\n');
|
|
5387
5602
|
// <- TODO: [๐ง ] Some smart aggregation of knowledge pieces, single-line vs multi-line vs mixed
|
|
5388
5603
|
}
|
|
5604
|
+
// TODO: !!!!!! Annotate + to new file
|
|
5605
|
+
function computeCosineSimilarity(embeddingVector1, embeddingVector2) {
|
|
5606
|
+
if (embeddingVector1.length !== embeddingVector2.length) {
|
|
5607
|
+
throw new TypeError('Embedding vectors must have the same length');
|
|
5608
|
+
}
|
|
5609
|
+
const dotProduct = embeddingVector1.reduce((sum, value, index) => sum + value * embeddingVector2[index], 0);
|
|
5610
|
+
const magnitude1 = Math.sqrt(embeddingVector1.reduce((sum, value) => sum + value * value, 0));
|
|
5611
|
+
const magnitude2 = Math.sqrt(embeddingVector2.reduce((sum, value) => sum + value * value, 0));
|
|
5612
|
+
return 1 - dotProduct / (magnitude1 * magnitude2);
|
|
5613
|
+
}
|
|
5614
|
+
/**
|
|
5615
|
+
* TODO: !!!! Verify if this is working
|
|
5616
|
+
* TODO: [โจ] Implement Better - use keyword search
|
|
5617
|
+
* TODO: [โจ] Examples of values
|
|
5618
|
+
*/
|
|
5389
5619
|
|
|
5390
5620
|
/**
|
|
5391
5621
|
* @@@
|
|
@@ -5393,9 +5623,9 @@ async function getKnowledgeForTask(options) {
|
|
|
5393
5623
|
* @private internal utility of `createPipelineExecutor`
|
|
5394
5624
|
*/
|
|
5395
5625
|
async function getReservedParametersForTask(options) {
|
|
5396
|
-
const { preparedPipeline, task, pipelineIdentification } = options;
|
|
5626
|
+
const { tools, preparedPipeline, task, pipelineIdentification } = options;
|
|
5397
5627
|
const context = await getContextForTask(); // <- [๐]
|
|
5398
|
-
const knowledge = await getKnowledgeForTask({ preparedPipeline, task });
|
|
5628
|
+
const knowledge = await getKnowledgeForTask({ tools, preparedPipeline, task });
|
|
5399
5629
|
const examples = await getExamplesForTask();
|
|
5400
5630
|
const currentDate = new Date().toISOString(); // <- TODO: [๐ง ][๐ฉ] Better
|
|
5401
5631
|
const modelName = RESERVED_PARAMETER_MISSING_VALUE;
|
|
@@ -5410,7 +5640,7 @@ async function getReservedParametersForTask(options) {
|
|
|
5410
5640
|
// Note: Doublecheck that ALL reserved parameters are defined:
|
|
5411
5641
|
for (const parameterName of RESERVED_PARAMETER_NAMES) {
|
|
5412
5642
|
if (reservedParameters[parameterName] === undefined) {
|
|
5413
|
-
throw new UnexpectedError(spaceTrim((block) => `
|
|
5643
|
+
throw new UnexpectedError(spaceTrim$1((block) => `
|
|
5414
5644
|
Reserved parameter {${parameterName}} is not defined
|
|
5415
5645
|
|
|
5416
5646
|
${block(pipelineIdentification)}
|
|
@@ -5438,7 +5668,7 @@ async function executeTask(options) {
|
|
|
5438
5668
|
const dependentParameterNames = new Set(currentTask.dependentParameterNames);
|
|
5439
5669
|
// TODO: [๐ฉ๐พโ๐คโ๐ฉ๐ป] Use here `mapAvailableToExpectedParameters`
|
|
5440
5670
|
if (union(difference(usedParameterNames, dependentParameterNames), difference(dependentParameterNames, usedParameterNames)).size !== 0) {
|
|
5441
|
-
throw new UnexpectedError(spaceTrim((block) => `
|
|
5671
|
+
throw new UnexpectedError(spaceTrim$1((block) => `
|
|
5442
5672
|
Dependent parameters are not consistent with used parameters:
|
|
5443
5673
|
|
|
5444
5674
|
Dependent parameters:
|
|
@@ -5457,6 +5687,7 @@ async function executeTask(options) {
|
|
|
5457
5687
|
}
|
|
5458
5688
|
const definedParameters = Object.freeze({
|
|
5459
5689
|
...(await getReservedParametersForTask({
|
|
5690
|
+
tools,
|
|
5460
5691
|
preparedPipeline,
|
|
5461
5692
|
task: currentTask,
|
|
5462
5693
|
pipelineIdentification,
|
|
@@ -5478,7 +5709,7 @@ async function executeTask(options) {
|
|
|
5478
5709
|
else if (!definedParameterNames.has(parameterName) && usedParameterNames.has(parameterName)) {
|
|
5479
5710
|
// Houston, we have a problem
|
|
5480
5711
|
// Note: Checking part is also done in `validatePipeline`, but itโs good to doublecheck
|
|
5481
|
-
throw new UnexpectedError(spaceTrim((block) => `
|
|
5712
|
+
throw new UnexpectedError(spaceTrim$1((block) => `
|
|
5482
5713
|
Parameter \`{${parameterName}}\` is NOT defined
|
|
5483
5714
|
BUT used in task "${currentTask.title || currentTask.name}"
|
|
5484
5715
|
|
|
@@ -5544,7 +5775,7 @@ function filterJustOutputParameters(options) {
|
|
|
5544
5775
|
for (const parameter of preparedPipeline.parameters.filter(({ isOutput }) => isOutput)) {
|
|
5545
5776
|
if (parametersToPass[parameter.name] === undefined) {
|
|
5546
5777
|
// [4]
|
|
5547
|
-
$warnings.push(new PipelineExecutionError(spaceTrim((block) => `
|
|
5778
|
+
$warnings.push(new PipelineExecutionError(spaceTrim$1((block) => `
|
|
5548
5779
|
Parameter \`{${parameter.name}}\` should be an output parameter, but it was not generated during pipeline execution
|
|
5549
5780
|
|
|
5550
5781
|
${block(pipelineIdentification)}
|
|
@@ -5619,7 +5850,7 @@ async function executePipeline(options) {
|
|
|
5619
5850
|
for (const parameterName of Object.keys(inputParameters)) {
|
|
5620
5851
|
const parameter = preparedPipeline.parameters.find(({ name }) => name === parameterName);
|
|
5621
5852
|
if (parameter === undefined) {
|
|
5622
|
-
warnings.push(new PipelineExecutionError(spaceTrim((block) => `
|
|
5853
|
+
warnings.push(new PipelineExecutionError(spaceTrim$1((block) => `
|
|
5623
5854
|
Extra parameter {${parameterName}} is being passed which is not part of the pipeline.
|
|
5624
5855
|
|
|
5625
5856
|
${block(pipelineIdentification)}
|
|
@@ -5634,7 +5865,7 @@ async function executePipeline(options) {
|
|
|
5634
5865
|
// TODO: [๐ง ] This should be also non-critical error
|
|
5635
5866
|
return exportJson({
|
|
5636
5867
|
name: 'pipelineExecutorResult',
|
|
5637
|
-
message: spaceTrim((block) => `
|
|
5868
|
+
message: spaceTrim$1((block) => `
|
|
5638
5869
|
Unuccessful PipelineExecutorResult (with extra parameter {${parameter.name}}) PipelineExecutorResult
|
|
5639
5870
|
|
|
5640
5871
|
${block(pipelineIdentification)}
|
|
@@ -5643,7 +5874,7 @@ async function executePipeline(options) {
|
|
|
5643
5874
|
value: {
|
|
5644
5875
|
isSuccessful: false,
|
|
5645
5876
|
errors: [
|
|
5646
|
-
new PipelineExecutionError(spaceTrim((block) => `
|
|
5877
|
+
new PipelineExecutionError(spaceTrim$1((block) => `
|
|
5647
5878
|
Parameter \`{${parameter.name}}\` is passed as input parameter but it is not input
|
|
5648
5879
|
|
|
5649
5880
|
${block(pipelineIdentification)}
|
|
@@ -5670,7 +5901,7 @@ async function executePipeline(options) {
|
|
|
5670
5901
|
while (unresovedTasks.length > 0) {
|
|
5671
5902
|
if (loopLimit-- < 0) {
|
|
5672
5903
|
// Note: Really UnexpectedError not LimitReachedError - this should be catched during validatePipeline
|
|
5673
|
-
throw new UnexpectedError(spaceTrim((block) => `
|
|
5904
|
+
throw new UnexpectedError(spaceTrim$1((block) => `
|
|
5674
5905
|
Loop limit reached during resolving parameters pipeline execution
|
|
5675
5906
|
|
|
5676
5907
|
${block(pipelineIdentification)}
|
|
@@ -5680,7 +5911,7 @@ async function executePipeline(options) {
|
|
|
5680
5911
|
if (!currentTask && resolving.length === 0) {
|
|
5681
5912
|
throw new UnexpectedError(
|
|
5682
5913
|
// TODO: [๐] DRY
|
|
5683
|
-
spaceTrim((block) => `
|
|
5914
|
+
spaceTrim$1((block) => `
|
|
5684
5915
|
Can not resolve some parameters:
|
|
5685
5916
|
|
|
5686
5917
|
${block(pipelineIdentification)}
|
|
@@ -5720,7 +5951,7 @@ async function executePipeline(options) {
|
|
|
5720
5951
|
tools,
|
|
5721
5952
|
onProgress(newOngoingResult) {
|
|
5722
5953
|
if (isReturned) {
|
|
5723
|
-
throw new UnexpectedError(spaceTrim((block) => `
|
|
5954
|
+
throw new UnexpectedError(spaceTrim$1((block) => `
|
|
5724
5955
|
Can not call \`onProgress\` after pipeline execution is finished
|
|
5725
5956
|
|
|
5726
5957
|
${block(pipelineIdentification)}
|
|
@@ -5736,7 +5967,7 @@ async function executePipeline(options) {
|
|
|
5736
5967
|
}
|
|
5737
5968
|
},
|
|
5738
5969
|
$executionReport: executionReport,
|
|
5739
|
-
pipelineIdentification: spaceTrim((block) => `
|
|
5970
|
+
pipelineIdentification: spaceTrim$1((block) => `
|
|
5740
5971
|
${block(pipelineIdentification)}
|
|
5741
5972
|
Task name: ${currentTask.name}
|
|
5742
5973
|
Task title: ${currentTask.title}
|
|
@@ -5757,9 +5988,7 @@ async function executePipeline(options) {
|
|
|
5757
5988
|
await Promise.all(resolving);
|
|
5758
5989
|
}
|
|
5759
5990
|
catch (error /* <- Note: [3] */) {
|
|
5760
|
-
|
|
5761
|
-
throw error;
|
|
5762
|
-
}
|
|
5991
|
+
assertsError(error);
|
|
5763
5992
|
// Note: No need to rethrow UnexpectedError
|
|
5764
5993
|
// if (error instanceof UnexpectedError) {
|
|
5765
5994
|
// Note: Count usage, [๐ง ] Maybe put to separate function executionReportJsonToUsage + DRY [๐คนโโ๏ธ]
|
|
@@ -5847,7 +6076,7 @@ function createPipelineExecutor(options) {
|
|
|
5847
6076
|
preparedPipeline = pipeline;
|
|
5848
6077
|
}
|
|
5849
6078
|
else if (isNotPreparedWarningSupressed !== true) {
|
|
5850
|
-
console.warn(spaceTrim((block) => `
|
|
6079
|
+
console.warn(spaceTrim$1((block) => `
|
|
5851
6080
|
Pipeline is not prepared
|
|
5852
6081
|
|
|
5853
6082
|
${block(pipelineIdentification)}
|
|
@@ -5871,7 +6100,7 @@ function createPipelineExecutor(options) {
|
|
|
5871
6100
|
inputParameters,
|
|
5872
6101
|
tools,
|
|
5873
6102
|
onProgress,
|
|
5874
|
-
pipelineIdentification: spaceTrim((block) => `
|
|
6103
|
+
pipelineIdentification: spaceTrim$1((block) => `
|
|
5875
6104
|
${block(pipelineIdentification)}
|
|
5876
6105
|
${runCount === 1 ? '' : `Run #${runCount}`}
|
|
5877
6106
|
`),
|
|
@@ -5969,13 +6198,13 @@ function $registeredLlmToolsMessage() {
|
|
|
5969
6198
|
});
|
|
5970
6199
|
const usedEnvMessage = `Unknown \`.env\` file` ;
|
|
5971
6200
|
if (metadata.length === 0) {
|
|
5972
|
-
return spaceTrim
|
|
6201
|
+
return spaceTrim((block) => `
|
|
5973
6202
|
No LLM providers are available.
|
|
5974
6203
|
|
|
5975
6204
|
${block(usedEnvMessage)}
|
|
5976
6205
|
`);
|
|
5977
6206
|
}
|
|
5978
|
-
return spaceTrim
|
|
6207
|
+
return spaceTrim((block) => `
|
|
5979
6208
|
|
|
5980
6209
|
${block(usedEnvMessage)}
|
|
5981
6210
|
|
|
@@ -6021,7 +6250,7 @@ function $registeredLlmToolsMessage() {
|
|
|
6021
6250
|
morePieces.push(`Not configured`); // <- Note: Can not be configured via environment variables
|
|
6022
6251
|
}
|
|
6023
6252
|
}
|
|
6024
|
-
let providerMessage = spaceTrim
|
|
6253
|
+
let providerMessage = spaceTrim(`
|
|
6025
6254
|
${i + 1}) **${title}** \`${className}\` from \`${packageName}\`
|
|
6026
6255
|
${morePieces.join('; ')}
|
|
6027
6256
|
`);
|
|
@@ -6061,7 +6290,7 @@ function createLlmToolsFromConfiguration(configuration, options = {}) {
|
|
|
6061
6290
|
.list()
|
|
6062
6291
|
.find(({ packageName, className }) => llmConfiguration.packageName === packageName && llmConfiguration.className === className);
|
|
6063
6292
|
if (registeredItem === undefined) {
|
|
6064
|
-
throw new Error(spaceTrim
|
|
6293
|
+
throw new Error(spaceTrim((block) => `
|
|
6065
6294
|
There is no constructor for LLM provider \`${llmConfiguration.className}\` from \`${llmConfiguration.packageName}\`
|
|
6066
6295
|
|
|
6067
6296
|
You have probably forgotten install and import the provider package.
|
|
@@ -6345,13 +6574,13 @@ function removeQuotes(text) {
|
|
|
6345
6574
|
* @public exported from `@promptbook/utils`
|
|
6346
6575
|
*/
|
|
6347
6576
|
function trimCodeBlock(value) {
|
|
6348
|
-
value = spaceTrim(value);
|
|
6577
|
+
value = spaceTrim$1(value);
|
|
6349
6578
|
if (!/^```[a-z]*(.*)```$/is.test(value)) {
|
|
6350
6579
|
return value;
|
|
6351
6580
|
}
|
|
6352
6581
|
value = value.replace(/^```[a-z]*/i, '');
|
|
6353
6582
|
value = value.replace(/```$/i, '');
|
|
6354
|
-
value = spaceTrim(value);
|
|
6583
|
+
value = spaceTrim$1(value);
|
|
6355
6584
|
return value;
|
|
6356
6585
|
}
|
|
6357
6586
|
|
|
@@ -6364,9 +6593,9 @@ function trimCodeBlock(value) {
|
|
|
6364
6593
|
* @public exported from `@promptbook/utils`
|
|
6365
6594
|
*/
|
|
6366
6595
|
function trimEndOfCodeBlock(value) {
|
|
6367
|
-
value = spaceTrim(value);
|
|
6596
|
+
value = spaceTrim$1(value);
|
|
6368
6597
|
value = value.replace(/```$/g, '');
|
|
6369
|
-
value = spaceTrim(value);
|
|
6598
|
+
value = spaceTrim$1(value);
|
|
6370
6599
|
return value;
|
|
6371
6600
|
}
|
|
6372
6601
|
|
|
@@ -6388,7 +6617,7 @@ function unwrapResult(text, options) {
|
|
|
6388
6617
|
let trimmedText = text;
|
|
6389
6618
|
// Remove leading and trailing spaces and newlines
|
|
6390
6619
|
if (isTrimmed) {
|
|
6391
|
-
trimmedText = spaceTrim(trimmedText);
|
|
6620
|
+
trimmedText = spaceTrim$1(trimmedText);
|
|
6392
6621
|
}
|
|
6393
6622
|
let processedText = trimmedText;
|
|
6394
6623
|
if (isIntroduceSentenceRemoved) {
|
|
@@ -6397,7 +6626,7 @@ function unwrapResult(text, options) {
|
|
|
6397
6626
|
// Remove the introduce sentence and quotes by replacing it with an empty string
|
|
6398
6627
|
processedText = processedText.replace(introduceSentenceRegex, '');
|
|
6399
6628
|
}
|
|
6400
|
-
processedText = spaceTrim(processedText);
|
|
6629
|
+
processedText = spaceTrim$1(processedText);
|
|
6401
6630
|
}
|
|
6402
6631
|
if (processedText.length < 3) {
|
|
6403
6632
|
return trimmedText;
|
|
@@ -6460,7 +6689,7 @@ function unwrapResult(text, options) {
|
|
|
6460
6689
|
function extractOneBlockFromMarkdown(markdown) {
|
|
6461
6690
|
const codeBlocks = extractAllBlocksFromMarkdown(markdown);
|
|
6462
6691
|
if (codeBlocks.length !== 1) {
|
|
6463
|
-
throw new ParseError(spaceTrim
|
|
6692
|
+
throw new ParseError(spaceTrim((block) => `
|
|
6464
6693
|
There should be exactly 1 code block in task section, found ${codeBlocks.length} code blocks
|
|
6465
6694
|
|
|
6466
6695
|
${block(codeBlocks.map((block, i) => `Block ${i + 1}:\n${block.content}`).join('\n\n\n'))}
|
|
@@ -6542,8 +6771,8 @@ class JavascriptEvalExecutionTools {
|
|
|
6542
6771
|
}
|
|
6543
6772
|
// Note: [๐]
|
|
6544
6773
|
// Note: Using direct eval, following variables are in same scope as eval call so they are accessible from inside the evaluated script:
|
|
6545
|
-
const spaceTrim = (_) => spaceTrim
|
|
6546
|
-
preserve(spaceTrim);
|
|
6774
|
+
const spaceTrim$1 = (_) => spaceTrim(_);
|
|
6775
|
+
preserve(spaceTrim$1);
|
|
6547
6776
|
const removeQuotes$1 = removeQuotes;
|
|
6548
6777
|
preserve(removeQuotes$1);
|
|
6549
6778
|
const unwrapResult$1 = unwrapResult;
|
|
@@ -6596,7 +6825,7 @@ class JavascriptEvalExecutionTools {
|
|
|
6596
6825
|
// TODO: DRY [๐ฏ]
|
|
6597
6826
|
const buildinFunctions = {
|
|
6598
6827
|
// TODO: [๐ฏ] DRY all these functions across the file
|
|
6599
|
-
spaceTrim,
|
|
6828
|
+
spaceTrim: spaceTrim$1,
|
|
6600
6829
|
removeQuotes: removeQuotes$1,
|
|
6601
6830
|
unwrapResult: unwrapResult$1,
|
|
6602
6831
|
trimEndOfCodeBlock: trimEndOfCodeBlock$1,
|
|
@@ -6633,7 +6862,7 @@ class JavascriptEvalExecutionTools {
|
|
|
6633
6862
|
.join('\n');
|
|
6634
6863
|
// script = templateParameters(script, parameters);
|
|
6635
6864
|
// <- TODO: [๐ง ][๐ฅณ] Should be this is one of two variants how to use parameters in script
|
|
6636
|
-
const statementToEvaluate = spaceTrim
|
|
6865
|
+
const statementToEvaluate = spaceTrim((block) => `
|
|
6637
6866
|
|
|
6638
6867
|
// Build-in functions:
|
|
6639
6868
|
${block(buildinFunctionsStatement)}
|
|
@@ -6648,7 +6877,7 @@ class JavascriptEvalExecutionTools {
|
|
|
6648
6877
|
(()=>{ ${script} })()
|
|
6649
6878
|
`);
|
|
6650
6879
|
if (this.options.isVerbose) {
|
|
6651
|
-
console.info(spaceTrim
|
|
6880
|
+
console.info(spaceTrim((block) => `
|
|
6652
6881
|
๐ Evaluating ${scriptLanguage} script:
|
|
6653
6882
|
|
|
6654
6883
|
${block(statementToEvaluate)}`));
|
|
@@ -6661,9 +6890,7 @@ class JavascriptEvalExecutionTools {
|
|
|
6661
6890
|
}
|
|
6662
6891
|
}
|
|
6663
6892
|
catch (error) {
|
|
6664
|
-
|
|
6665
|
-
throw error;
|
|
6666
|
-
}
|
|
6893
|
+
assertsError(error);
|
|
6667
6894
|
if (error instanceof ReferenceError) {
|
|
6668
6895
|
const undefinedName = error.message.split(' ')[0];
|
|
6669
6896
|
/*
|
|
@@ -6672,7 +6899,7 @@ class JavascriptEvalExecutionTools {
|
|
|
6672
6899
|
To: [PipelineExecutionError: Parameter `{thing}` is not defined],
|
|
6673
6900
|
*/
|
|
6674
6901
|
if (!statementToEvaluate.includes(undefinedName + '(')) {
|
|
6675
|
-
throw new PipelineExecutionError(spaceTrim
|
|
6902
|
+
throw new PipelineExecutionError(spaceTrim((block) => `
|
|
6676
6903
|
|
|
6677
6904
|
Parameter \`{${undefinedName}}\` is not defined
|
|
6678
6905
|
|
|
@@ -6694,7 +6921,7 @@ class JavascriptEvalExecutionTools {
|
|
|
6694
6921
|
`));
|
|
6695
6922
|
}
|
|
6696
6923
|
else {
|
|
6697
|
-
throw new PipelineExecutionError(spaceTrim
|
|
6924
|
+
throw new PipelineExecutionError(spaceTrim((block) => `
|
|
6698
6925
|
Function ${undefinedName}() is not defined
|
|
6699
6926
|
|
|
6700
6927
|
- Make sure that the function is one of built-in functions
|
|
@@ -6743,6 +6970,604 @@ async function $provideScriptingForNode(options) {
|
|
|
6743
6970
|
* Note: [๐ข] Code in this file should never be never released in packages that could be imported into browser environment
|
|
6744
6971
|
*/
|
|
6745
6972
|
|
|
6973
|
+
// TODO: !!!! List running services from REMOTE_SERVER_URLS
|
|
6974
|
+
// TODO: !!!! Import directly from YML
|
|
6975
|
+
/**
|
|
6976
|
+
* @private !!!! Decide how to expose this
|
|
6977
|
+
*/
|
|
6978
|
+
const openapiJson = {
|
|
6979
|
+
openapi: '3.0.0',
|
|
6980
|
+
info: {
|
|
6981
|
+
title: 'Promptbook Remote Server API (!!!! From YML)',
|
|
6982
|
+
version: '1.0.0',
|
|
6983
|
+
description: 'API documentation for the Promptbook Remote Server',
|
|
6984
|
+
},
|
|
6985
|
+
paths: {
|
|
6986
|
+
'/': {
|
|
6987
|
+
get: {
|
|
6988
|
+
summary: 'Get server details',
|
|
6989
|
+
description: 'Returns details about the Promptbook server.',
|
|
6990
|
+
responses: {
|
|
6991
|
+
'200': {
|
|
6992
|
+
description: 'Server details in markdown format.',
|
|
6993
|
+
content: {
|
|
6994
|
+
'text/markdown': {
|
|
6995
|
+
schema: {
|
|
6996
|
+
type: 'string',
|
|
6997
|
+
},
|
|
6998
|
+
},
|
|
6999
|
+
},
|
|
7000
|
+
},
|
|
7001
|
+
},
|
|
7002
|
+
},
|
|
7003
|
+
},
|
|
7004
|
+
'/login': {
|
|
7005
|
+
post: {
|
|
7006
|
+
summary: 'Login to the server',
|
|
7007
|
+
description: 'Login to the server and get identification.',
|
|
7008
|
+
requestBody: {
|
|
7009
|
+
required: true,
|
|
7010
|
+
content: {
|
|
7011
|
+
'application/json': {
|
|
7012
|
+
schema: {
|
|
7013
|
+
type: 'object',
|
|
7014
|
+
properties: {
|
|
7015
|
+
username: {
|
|
7016
|
+
type: 'string',
|
|
7017
|
+
},
|
|
7018
|
+
password: {
|
|
7019
|
+
type: 'string',
|
|
7020
|
+
},
|
|
7021
|
+
appId: {
|
|
7022
|
+
type: 'string',
|
|
7023
|
+
},
|
|
7024
|
+
},
|
|
7025
|
+
},
|
|
7026
|
+
},
|
|
7027
|
+
},
|
|
7028
|
+
},
|
|
7029
|
+
responses: {
|
|
7030
|
+
'201': {
|
|
7031
|
+
description: 'Successful login',
|
|
7032
|
+
content: {
|
|
7033
|
+
'application/json': {
|
|
7034
|
+
schema: {
|
|
7035
|
+
type: 'object',
|
|
7036
|
+
properties: {
|
|
7037
|
+
isSuccess: {
|
|
7038
|
+
type: 'boolean',
|
|
7039
|
+
},
|
|
7040
|
+
message: {
|
|
7041
|
+
type: 'string',
|
|
7042
|
+
},
|
|
7043
|
+
error: {
|
|
7044
|
+
type: 'object',
|
|
7045
|
+
},
|
|
7046
|
+
identification: {
|
|
7047
|
+
type: 'object',
|
|
7048
|
+
},
|
|
7049
|
+
},
|
|
7050
|
+
},
|
|
7051
|
+
},
|
|
7052
|
+
},
|
|
7053
|
+
},
|
|
7054
|
+
'400': {
|
|
7055
|
+
description: 'Bad request or login failed',
|
|
7056
|
+
content: {
|
|
7057
|
+
'application/json': {
|
|
7058
|
+
schema: {
|
|
7059
|
+
type: 'object',
|
|
7060
|
+
properties: {
|
|
7061
|
+
error: {
|
|
7062
|
+
type: 'object',
|
|
7063
|
+
},
|
|
7064
|
+
},
|
|
7065
|
+
},
|
|
7066
|
+
},
|
|
7067
|
+
},
|
|
7068
|
+
},
|
|
7069
|
+
'401': {
|
|
7070
|
+
description: 'Authentication error',
|
|
7071
|
+
content: {
|
|
7072
|
+
'application/json': {
|
|
7073
|
+
schema: {
|
|
7074
|
+
type: 'object',
|
|
7075
|
+
properties: {
|
|
7076
|
+
isSuccess: {
|
|
7077
|
+
type: 'boolean',
|
|
7078
|
+
enum: [false],
|
|
7079
|
+
},
|
|
7080
|
+
message: {
|
|
7081
|
+
type: 'string',
|
|
7082
|
+
},
|
|
7083
|
+
error: {
|
|
7084
|
+
type: 'object',
|
|
7085
|
+
},
|
|
7086
|
+
},
|
|
7087
|
+
},
|
|
7088
|
+
},
|
|
7089
|
+
},
|
|
7090
|
+
},
|
|
7091
|
+
},
|
|
7092
|
+
},
|
|
7093
|
+
},
|
|
7094
|
+
'/books': {
|
|
7095
|
+
get: {
|
|
7096
|
+
summary: 'List all books',
|
|
7097
|
+
description: 'Returns a list of all available books in the collection.',
|
|
7098
|
+
responses: {
|
|
7099
|
+
'200': {
|
|
7100
|
+
description: 'A list of books.',
|
|
7101
|
+
content: {
|
|
7102
|
+
'application/json': {
|
|
7103
|
+
schema: {
|
|
7104
|
+
type: 'array',
|
|
7105
|
+
items: {
|
|
7106
|
+
type: 'string',
|
|
7107
|
+
},
|
|
7108
|
+
},
|
|
7109
|
+
},
|
|
7110
|
+
},
|
|
7111
|
+
},
|
|
7112
|
+
'500': {
|
|
7113
|
+
description: 'No collection available',
|
|
7114
|
+
content: {
|
|
7115
|
+
'text/plain': {
|
|
7116
|
+
schema: {
|
|
7117
|
+
type: 'string',
|
|
7118
|
+
},
|
|
7119
|
+
},
|
|
7120
|
+
},
|
|
7121
|
+
},
|
|
7122
|
+
},
|
|
7123
|
+
},
|
|
7124
|
+
},
|
|
7125
|
+
'/books/{bookId}': {
|
|
7126
|
+
get: {
|
|
7127
|
+
summary: 'Get book content',
|
|
7128
|
+
description: 'Returns the content of a specific book.',
|
|
7129
|
+
parameters: [
|
|
7130
|
+
{
|
|
7131
|
+
in: 'path',
|
|
7132
|
+
name: 'bookId',
|
|
7133
|
+
required: true,
|
|
7134
|
+
schema: {
|
|
7135
|
+
type: 'string',
|
|
7136
|
+
},
|
|
7137
|
+
description: 'The ID of the book to retrieve.',
|
|
7138
|
+
},
|
|
7139
|
+
],
|
|
7140
|
+
responses: {
|
|
7141
|
+
'200': {
|
|
7142
|
+
description: 'The content of the book.',
|
|
7143
|
+
content: {
|
|
7144
|
+
'text/markdown': {
|
|
7145
|
+
schema: {
|
|
7146
|
+
type: 'string',
|
|
7147
|
+
},
|
|
7148
|
+
},
|
|
7149
|
+
},
|
|
7150
|
+
},
|
|
7151
|
+
'404': {
|
|
7152
|
+
description: 'Book not found.',
|
|
7153
|
+
content: {
|
|
7154
|
+
'application/json': {
|
|
7155
|
+
schema: {
|
|
7156
|
+
type: 'object',
|
|
7157
|
+
properties: {
|
|
7158
|
+
error: {
|
|
7159
|
+
type: 'object',
|
|
7160
|
+
},
|
|
7161
|
+
},
|
|
7162
|
+
},
|
|
7163
|
+
},
|
|
7164
|
+
},
|
|
7165
|
+
},
|
|
7166
|
+
'500': {
|
|
7167
|
+
description: 'No collection available',
|
|
7168
|
+
content: {
|
|
7169
|
+
'text/plain': {
|
|
7170
|
+
schema: {
|
|
7171
|
+
type: 'string',
|
|
7172
|
+
},
|
|
7173
|
+
},
|
|
7174
|
+
},
|
|
7175
|
+
},
|
|
7176
|
+
},
|
|
7177
|
+
},
|
|
7178
|
+
},
|
|
7179
|
+
'/executions': {
|
|
7180
|
+
get: {
|
|
7181
|
+
summary: 'List all executions',
|
|
7182
|
+
description: 'Returns a list of all running execution tasks.',
|
|
7183
|
+
responses: {
|
|
7184
|
+
'200': {
|
|
7185
|
+
description: 'A list of execution tasks.',
|
|
7186
|
+
content: {
|
|
7187
|
+
'application/json': {
|
|
7188
|
+
schema: {
|
|
7189
|
+
type: 'array',
|
|
7190
|
+
items: {
|
|
7191
|
+
type: 'object',
|
|
7192
|
+
properties: {
|
|
7193
|
+
nonce: {
|
|
7194
|
+
type: 'string',
|
|
7195
|
+
},
|
|
7196
|
+
taskId: {
|
|
7197
|
+
type: 'string',
|
|
7198
|
+
},
|
|
7199
|
+
taskType: {
|
|
7200
|
+
type: 'string',
|
|
7201
|
+
},
|
|
7202
|
+
status: {
|
|
7203
|
+
type: 'string',
|
|
7204
|
+
},
|
|
7205
|
+
createdAt: {
|
|
7206
|
+
type: 'string',
|
|
7207
|
+
format: 'date-time',
|
|
7208
|
+
},
|
|
7209
|
+
updatedAt: {
|
|
7210
|
+
type: 'string',
|
|
7211
|
+
format: 'date-time',
|
|
7212
|
+
},
|
|
7213
|
+
},
|
|
7214
|
+
},
|
|
7215
|
+
},
|
|
7216
|
+
},
|
|
7217
|
+
},
|
|
7218
|
+
},
|
|
7219
|
+
},
|
|
7220
|
+
},
|
|
7221
|
+
},
|
|
7222
|
+
'/executions/last': {
|
|
7223
|
+
get: {
|
|
7224
|
+
summary: 'Get the last execution',
|
|
7225
|
+
description: 'Returns details of the last execution task.',
|
|
7226
|
+
responses: {
|
|
7227
|
+
'200': {
|
|
7228
|
+
description: 'The last execution task with full details.',
|
|
7229
|
+
content: {
|
|
7230
|
+
'application/json': {
|
|
7231
|
+
schema: {
|
|
7232
|
+
type: 'object',
|
|
7233
|
+
properties: {
|
|
7234
|
+
nonce: {
|
|
7235
|
+
type: 'string',
|
|
7236
|
+
},
|
|
7237
|
+
taskId: {
|
|
7238
|
+
type: 'string',
|
|
7239
|
+
},
|
|
7240
|
+
taskType: {
|
|
7241
|
+
type: 'string',
|
|
7242
|
+
},
|
|
7243
|
+
status: {
|
|
7244
|
+
type: 'string',
|
|
7245
|
+
},
|
|
7246
|
+
errors: {
|
|
7247
|
+
type: 'array',
|
|
7248
|
+
items: {
|
|
7249
|
+
type: 'object',
|
|
7250
|
+
},
|
|
7251
|
+
},
|
|
7252
|
+
warnings: {
|
|
7253
|
+
type: 'array',
|
|
7254
|
+
items: {
|
|
7255
|
+
type: 'object',
|
|
7256
|
+
},
|
|
7257
|
+
},
|
|
7258
|
+
createdAt: {
|
|
7259
|
+
type: 'string',
|
|
7260
|
+
format: 'date-time',
|
|
7261
|
+
},
|
|
7262
|
+
updatedAt: {
|
|
7263
|
+
type: 'string',
|
|
7264
|
+
format: 'date-time',
|
|
7265
|
+
},
|
|
7266
|
+
currentValue: {
|
|
7267
|
+
type: 'object',
|
|
7268
|
+
},
|
|
7269
|
+
},
|
|
7270
|
+
},
|
|
7271
|
+
},
|
|
7272
|
+
},
|
|
7273
|
+
},
|
|
7274
|
+
'404': {
|
|
7275
|
+
description: 'No execution tasks found.',
|
|
7276
|
+
content: {
|
|
7277
|
+
'text/plain': {
|
|
7278
|
+
schema: {
|
|
7279
|
+
type: 'string',
|
|
7280
|
+
},
|
|
7281
|
+
},
|
|
7282
|
+
},
|
|
7283
|
+
},
|
|
7284
|
+
},
|
|
7285
|
+
},
|
|
7286
|
+
},
|
|
7287
|
+
'/executions/{taskId}': {
|
|
7288
|
+
get: {
|
|
7289
|
+
summary: 'Get specific execution',
|
|
7290
|
+
description: 'Returns details of a specific execution task.',
|
|
7291
|
+
parameters: [
|
|
7292
|
+
{
|
|
7293
|
+
in: 'path',
|
|
7294
|
+
name: 'taskId',
|
|
7295
|
+
required: true,
|
|
7296
|
+
schema: {
|
|
7297
|
+
type: 'string',
|
|
7298
|
+
},
|
|
7299
|
+
description: 'The ID of the execution task to retrieve.',
|
|
7300
|
+
},
|
|
7301
|
+
],
|
|
7302
|
+
responses: {
|
|
7303
|
+
'200': {
|
|
7304
|
+
description: 'The execution task with full details.',
|
|
7305
|
+
content: {
|
|
7306
|
+
'application/json': {
|
|
7307
|
+
schema: {
|
|
7308
|
+
type: 'object',
|
|
7309
|
+
properties: {
|
|
7310
|
+
nonce: {
|
|
7311
|
+
type: 'string',
|
|
7312
|
+
},
|
|
7313
|
+
taskId: {
|
|
7314
|
+
type: 'string',
|
|
7315
|
+
},
|
|
7316
|
+
taskType: {
|
|
7317
|
+
type: 'string',
|
|
7318
|
+
},
|
|
7319
|
+
status: {
|
|
7320
|
+
type: 'string',
|
|
7321
|
+
},
|
|
7322
|
+
errors: {
|
|
7323
|
+
type: 'array',
|
|
7324
|
+
items: {
|
|
7325
|
+
type: 'object',
|
|
7326
|
+
},
|
|
7327
|
+
},
|
|
7328
|
+
warnings: {
|
|
7329
|
+
type: 'array',
|
|
7330
|
+
items: {
|
|
7331
|
+
type: 'object',
|
|
7332
|
+
},
|
|
7333
|
+
},
|
|
7334
|
+
createdAt: {
|
|
7335
|
+
type: 'string',
|
|
7336
|
+
format: 'date-time',
|
|
7337
|
+
},
|
|
7338
|
+
updatedAt: {
|
|
7339
|
+
type: 'string',
|
|
7340
|
+
format: 'date-time',
|
|
7341
|
+
},
|
|
7342
|
+
currentValue: {
|
|
7343
|
+
type: 'object',
|
|
7344
|
+
},
|
|
7345
|
+
},
|
|
7346
|
+
},
|
|
7347
|
+
},
|
|
7348
|
+
},
|
|
7349
|
+
},
|
|
7350
|
+
'404': {
|
|
7351
|
+
description: 'Execution task not found.',
|
|
7352
|
+
content: {
|
|
7353
|
+
'text/plain': {
|
|
7354
|
+
schema: {
|
|
7355
|
+
type: 'string',
|
|
7356
|
+
},
|
|
7357
|
+
},
|
|
7358
|
+
},
|
|
7359
|
+
},
|
|
7360
|
+
},
|
|
7361
|
+
},
|
|
7362
|
+
},
|
|
7363
|
+
'/executions/new': {
|
|
7364
|
+
post: {
|
|
7365
|
+
summary: 'Start a new execution',
|
|
7366
|
+
description: 'Starts a new execution task for a given pipeline.',
|
|
7367
|
+
requestBody: {
|
|
7368
|
+
required: true,
|
|
7369
|
+
content: {
|
|
7370
|
+
'application/json': {
|
|
7371
|
+
schema: {
|
|
7372
|
+
type: 'object',
|
|
7373
|
+
properties: {
|
|
7374
|
+
pipelineUrl: {
|
|
7375
|
+
type: 'string',
|
|
7376
|
+
description: 'URL of the pipeline to execute',
|
|
7377
|
+
},
|
|
7378
|
+
book: {
|
|
7379
|
+
type: 'string',
|
|
7380
|
+
description: 'Alternative field for pipelineUrl',
|
|
7381
|
+
},
|
|
7382
|
+
inputParameters: {
|
|
7383
|
+
type: 'object',
|
|
7384
|
+
description: 'Parameters for pipeline execution',
|
|
7385
|
+
},
|
|
7386
|
+
identification: {
|
|
7387
|
+
type: 'object',
|
|
7388
|
+
description: 'User identification data',
|
|
7389
|
+
},
|
|
7390
|
+
},
|
|
7391
|
+
},
|
|
7392
|
+
},
|
|
7393
|
+
},
|
|
7394
|
+
},
|
|
7395
|
+
responses: {
|
|
7396
|
+
'200': {
|
|
7397
|
+
description: 'The newly created execution task.',
|
|
7398
|
+
content: {
|
|
7399
|
+
'application/json': {
|
|
7400
|
+
schema: {
|
|
7401
|
+
type: 'object',
|
|
7402
|
+
},
|
|
7403
|
+
},
|
|
7404
|
+
},
|
|
7405
|
+
},
|
|
7406
|
+
'400': {
|
|
7407
|
+
description: 'Invalid input.',
|
|
7408
|
+
content: {
|
|
7409
|
+
'application/json': {
|
|
7410
|
+
schema: {
|
|
7411
|
+
type: 'object',
|
|
7412
|
+
properties: {
|
|
7413
|
+
error: {
|
|
7414
|
+
type: 'object',
|
|
7415
|
+
},
|
|
7416
|
+
},
|
|
7417
|
+
},
|
|
7418
|
+
},
|
|
7419
|
+
},
|
|
7420
|
+
},
|
|
7421
|
+
'404': {
|
|
7422
|
+
description: 'Pipeline not found.',
|
|
7423
|
+
content: {
|
|
7424
|
+
'text/plain': {
|
|
7425
|
+
schema: {
|
|
7426
|
+
type: 'string',
|
|
7427
|
+
},
|
|
7428
|
+
},
|
|
7429
|
+
},
|
|
7430
|
+
},
|
|
7431
|
+
},
|
|
7432
|
+
},
|
|
7433
|
+
},
|
|
7434
|
+
'/api-docs': {
|
|
7435
|
+
get: {
|
|
7436
|
+
summary: 'API documentation UI',
|
|
7437
|
+
description: 'Swagger UI for API documentation',
|
|
7438
|
+
responses: {
|
|
7439
|
+
'200': {
|
|
7440
|
+
description: 'HTML Swagger UI',
|
|
7441
|
+
},
|
|
7442
|
+
},
|
|
7443
|
+
},
|
|
7444
|
+
},
|
|
7445
|
+
'/swagger': {
|
|
7446
|
+
get: {
|
|
7447
|
+
summary: 'API documentation UI (alternative path)',
|
|
7448
|
+
description: 'Swagger UI for API documentation',
|
|
7449
|
+
responses: {
|
|
7450
|
+
'200': {
|
|
7451
|
+
description: 'HTML Swagger UI',
|
|
7452
|
+
},
|
|
7453
|
+
},
|
|
7454
|
+
},
|
|
7455
|
+
},
|
|
7456
|
+
'/openapi': {
|
|
7457
|
+
get: {
|
|
7458
|
+
summary: 'OpenAPI specification',
|
|
7459
|
+
description: 'Returns the OpenAPI JSON specification',
|
|
7460
|
+
responses: {
|
|
7461
|
+
'200': {
|
|
7462
|
+
description: 'OpenAPI specification',
|
|
7463
|
+
content: {
|
|
7464
|
+
'application/json': {
|
|
7465
|
+
schema: {
|
|
7466
|
+
type: 'object',
|
|
7467
|
+
},
|
|
7468
|
+
},
|
|
7469
|
+
},
|
|
7470
|
+
},
|
|
7471
|
+
},
|
|
7472
|
+
},
|
|
7473
|
+
},
|
|
7474
|
+
},
|
|
7475
|
+
components: {
|
|
7476
|
+
schemas: {
|
|
7477
|
+
Error: {
|
|
7478
|
+
type: 'object',
|
|
7479
|
+
properties: {
|
|
7480
|
+
error: {
|
|
7481
|
+
type: 'object',
|
|
7482
|
+
},
|
|
7483
|
+
},
|
|
7484
|
+
},
|
|
7485
|
+
ExecutionTaskSummary: {
|
|
7486
|
+
type: 'object',
|
|
7487
|
+
properties: {
|
|
7488
|
+
nonce: {
|
|
7489
|
+
type: 'string',
|
|
7490
|
+
},
|
|
7491
|
+
taskId: {
|
|
7492
|
+
type: 'string',
|
|
7493
|
+
},
|
|
7494
|
+
taskType: {
|
|
7495
|
+
type: 'string',
|
|
7496
|
+
},
|
|
7497
|
+
status: {
|
|
7498
|
+
type: 'string',
|
|
7499
|
+
},
|
|
7500
|
+
createdAt: {
|
|
7501
|
+
type: 'string',
|
|
7502
|
+
format: 'date-time',
|
|
7503
|
+
},
|
|
7504
|
+
updatedAt: {
|
|
7505
|
+
type: 'string',
|
|
7506
|
+
format: 'date-time',
|
|
7507
|
+
},
|
|
7508
|
+
},
|
|
7509
|
+
},
|
|
7510
|
+
ExecutionTaskFull: {
|
|
7511
|
+
type: 'object',
|
|
7512
|
+
properties: {
|
|
7513
|
+
nonce: {
|
|
7514
|
+
type: 'string',
|
|
7515
|
+
},
|
|
7516
|
+
taskId: {
|
|
7517
|
+
type: 'string',
|
|
7518
|
+
},
|
|
7519
|
+
taskType: {
|
|
7520
|
+
type: 'string',
|
|
7521
|
+
},
|
|
7522
|
+
status: {
|
|
7523
|
+
type: 'string',
|
|
7524
|
+
},
|
|
7525
|
+
errors: {
|
|
7526
|
+
type: 'array',
|
|
7527
|
+
items: {
|
|
7528
|
+
type: 'object',
|
|
7529
|
+
},
|
|
7530
|
+
},
|
|
7531
|
+
warnings: {
|
|
7532
|
+
type: 'array',
|
|
7533
|
+
items: {
|
|
7534
|
+
type: 'object',
|
|
7535
|
+
},
|
|
7536
|
+
},
|
|
7537
|
+
createdAt: {
|
|
7538
|
+
type: 'string',
|
|
7539
|
+
format: 'date-time',
|
|
7540
|
+
},
|
|
7541
|
+
updatedAt: {
|
|
7542
|
+
type: 'string',
|
|
7543
|
+
format: 'date-time',
|
|
7544
|
+
},
|
|
7545
|
+
currentValue: {
|
|
7546
|
+
type: 'object',
|
|
7547
|
+
},
|
|
7548
|
+
},
|
|
7549
|
+
},
|
|
7550
|
+
},
|
|
7551
|
+
},
|
|
7552
|
+
tags: [
|
|
7553
|
+
{
|
|
7554
|
+
name: 'Books',
|
|
7555
|
+
description: 'Operations related to books and pipelines',
|
|
7556
|
+
},
|
|
7557
|
+
{
|
|
7558
|
+
name: 'Executions',
|
|
7559
|
+
description: 'Operations related to execution tasks',
|
|
7560
|
+
},
|
|
7561
|
+
{
|
|
7562
|
+
name: 'Authentication',
|
|
7563
|
+
description: 'Authentication operations',
|
|
7564
|
+
},
|
|
7565
|
+
],
|
|
7566
|
+
};
|
|
7567
|
+
/**
|
|
7568
|
+
* Note: [๐] Ignore a discrepancy between file name and entity name
|
|
7569
|
+
*/
|
|
7570
|
+
|
|
6746
7571
|
/**
|
|
6747
7572
|
* Remote server is a proxy server that uses its execution tools internally and exposes the executor interface externally.
|
|
6748
7573
|
*
|
|
@@ -6753,7 +7578,7 @@ async function $provideScriptingForNode(options) {
|
|
|
6753
7578
|
* @public exported from `@promptbook/remote-server`
|
|
6754
7579
|
*/
|
|
6755
7580
|
function startRemoteServer(options) {
|
|
6756
|
-
const { port, collection, createLlmExecutionTools, isAnonymousModeAllowed, isApplicationModeAllowed, isVerbose = DEFAULT_IS_VERBOSE, login, } = {
|
|
7581
|
+
const { port, collection, createLlmExecutionTools, createExecutionTools, isAnonymousModeAllowed, isApplicationModeAllowed, isVerbose = DEFAULT_IS_VERBOSE, login, } = {
|
|
6757
7582
|
isAnonymousModeAllowed: false,
|
|
6758
7583
|
isApplicationModeAllowed: false,
|
|
6759
7584
|
collection: null,
|
|
@@ -6761,22 +7586,6 @@ function startRemoteServer(options) {
|
|
|
6761
7586
|
login: null,
|
|
6762
7587
|
...options,
|
|
6763
7588
|
};
|
|
6764
|
-
// <- TODO: [๐ฆช] Some helper type to be able to use discriminant union types with destructuring
|
|
6765
|
-
let { rootPath = '/' } = options;
|
|
6766
|
-
if (!rootPath.startsWith('/')) {
|
|
6767
|
-
rootPath = `/${rootPath}`;
|
|
6768
|
-
} /* not else */
|
|
6769
|
-
if (rootPath.endsWith('/')) {
|
|
6770
|
-
rootPath = rootPath.slice(0, -1);
|
|
6771
|
-
} /* not else */
|
|
6772
|
-
if (rootPath === '/') {
|
|
6773
|
-
rootPath = '';
|
|
6774
|
-
}
|
|
6775
|
-
const socketioPath = '/' +
|
|
6776
|
-
`${rootPath}/socket.io`
|
|
6777
|
-
.split('/')
|
|
6778
|
-
.filter((part) => part !== '')
|
|
6779
|
-
.join('/');
|
|
6780
7589
|
const startupDate = new Date();
|
|
6781
7590
|
async function getExecutionToolsFromIdentification(identification) {
|
|
6782
7591
|
if (identification === null || identification === undefined) {
|
|
@@ -6799,23 +7608,25 @@ function startRemoteServer(options) {
|
|
|
6799
7608
|
}
|
|
6800
7609
|
else if (isAnonymous === false && createLlmExecutionTools !== null) {
|
|
6801
7610
|
// Note: Application mode
|
|
6802
|
-
|
|
6803
|
-
llm = await createLlmExecutionTools({
|
|
6804
|
-
appId,
|
|
6805
|
-
userId,
|
|
6806
|
-
customOptions,
|
|
6807
|
-
});
|
|
7611
|
+
llm = await createLlmExecutionTools(identification);
|
|
6808
7612
|
}
|
|
6809
7613
|
else {
|
|
6810
7614
|
throw new PipelineExecutionError(`You must provide either llmToolsConfiguration or non-anonymous mode must be propperly configured`);
|
|
6811
7615
|
}
|
|
6812
|
-
const
|
|
6813
|
-
const
|
|
7616
|
+
const customExecutionTools = createExecutionTools ? await createExecutionTools(identification) : {};
|
|
7617
|
+
const fs = customExecutionTools.fs || $provideFilesystemForNode();
|
|
7618
|
+
const executables = customExecutionTools.executables || (await $provideExecutablesForNode());
|
|
7619
|
+
const scrapers = customExecutionTools.scrapers || (await $provideScrapersForNode({ fs, llm, executables }));
|
|
7620
|
+
const script = customExecutionTools.script || (await $provideScriptingForNode({}));
|
|
7621
|
+
const fetch = customExecutionTools.fetch || promptbookFetch;
|
|
7622
|
+
const userInterface = customExecutionTools.userInterface || undefined;
|
|
6814
7623
|
const tools = {
|
|
6815
7624
|
llm,
|
|
6816
7625
|
fs,
|
|
6817
|
-
scrapers
|
|
6818
|
-
script
|
|
7626
|
+
scrapers,
|
|
7627
|
+
script,
|
|
7628
|
+
fetch,
|
|
7629
|
+
userInterface,
|
|
6819
7630
|
};
|
|
6820
7631
|
return tools;
|
|
6821
7632
|
}
|
|
@@ -6825,44 +7636,32 @@ function startRemoteServer(options) {
|
|
|
6825
7636
|
response.setHeader('X-Powered-By', 'Promptbook engine');
|
|
6826
7637
|
next();
|
|
6827
7638
|
});
|
|
6828
|
-
|
|
6829
|
-
|
|
6830
|
-
|
|
6831
|
-
|
|
6832
|
-
|
|
6833
|
-
version: '1.0.0',
|
|
6834
|
-
description: 'API documentation for the Promptbook Remote Server',
|
|
6835
|
-
},
|
|
6836
|
-
servers: [
|
|
6837
|
-
{
|
|
6838
|
-
url: `http://localhost:${port}${rootPath}`,
|
|
6839
|
-
// <- TODO: !!!!! Probbably: Pass `remoteServerUrl` instead of `port` and `rootPath`
|
|
6840
|
-
},
|
|
6841
|
-
],
|
|
7639
|
+
// TODO: !!!! Expose openapiJson to consumer and also allow to add new routes
|
|
7640
|
+
app.use(OpenApiValidator.middleware({
|
|
7641
|
+
apiSpec: openapiJson,
|
|
7642
|
+
ignorePaths(path) {
|
|
7643
|
+
return path.startsWith('/api-docs') || path.startsWith('/swagger') || path.startsWith('/openapi');
|
|
6842
7644
|
},
|
|
6843
|
-
|
|
6844
|
-
|
|
6845
|
-
|
|
6846
|
-
app.use([`/api-docs`,
|
|
7645
|
+
validateRequests: true,
|
|
7646
|
+
validateResponses: true,
|
|
7647
|
+
}));
|
|
7648
|
+
app.use([`/api-docs`, `/swagger`], swaggerUi.serve, swaggerUi.setup(openapiJson, {
|
|
7649
|
+
// customCss: '.swagger-ui .topbar { display: none }',
|
|
7650
|
+
// customSiteTitle: 'BRJ API',
|
|
7651
|
+
// customfavIcon: 'https://brj.app/favicon.ico',
|
|
7652
|
+
}));
|
|
7653
|
+
app.get(`/openapi`, (request, response) => {
|
|
7654
|
+
response.json(openapiJson);
|
|
7655
|
+
});
|
|
6847
7656
|
const runningExecutionTasks = [];
|
|
6848
7657
|
// <- TODO: [๐คฌ] Identify the users
|
|
6849
7658
|
// TODO: [๐ง ] Do here some garbage collection of finished tasks
|
|
6850
|
-
|
|
6851
|
-
* @swagger
|
|
6852
|
-
* /:
|
|
6853
|
-
* get:
|
|
6854
|
-
* summary: Get server details
|
|
6855
|
-
* description: Returns details about the Promptbook server.
|
|
6856
|
-
* responses:
|
|
6857
|
-
* 200:
|
|
6858
|
-
* description: Server details in markdown format.
|
|
6859
|
-
*/
|
|
6860
|
-
app.get(['/', rootPath], async (request, response) => {
|
|
7659
|
+
app.get('/', async (request, response) => {
|
|
6861
7660
|
var _a;
|
|
6862
7661
|
if ((_a = request.url) === null || _a === void 0 ? void 0 : _a.includes('socket.io')) {
|
|
6863
7662
|
return;
|
|
6864
7663
|
}
|
|
6865
|
-
response.type('text/markdown').send(await spaceTrim(async (block) => `
|
|
7664
|
+
response.type('text/markdown').send(await spaceTrim$1(async (block) => `
|
|
6866
7665
|
# Promptbook
|
|
6867
7666
|
|
|
6868
7667
|
> ${block(CLAIM)}
|
|
@@ -6876,8 +7675,6 @@ function startRemoteServer(options) {
|
|
|
6876
7675
|
## Details
|
|
6877
7676
|
|
|
6878
7677
|
**Server port:** ${port}
|
|
6879
|
-
**Server root path:** ${rootPath}
|
|
6880
|
-
**Socket.io path:** ${socketioPath}
|
|
6881
7678
|
**Startup date:** ${startupDate.toISOString()}
|
|
6882
7679
|
**Anonymouse mode:** ${isAnonymousModeAllowed ? 'enabled' : 'disabled'}
|
|
6883
7680
|
**Application mode:** ${isApplicationModeAllowed ? 'enabled' : 'disabled'}
|
|
@@ -6916,38 +7713,7 @@ function startRemoteServer(options) {
|
|
|
6916
7713
|
https://github.com/webgptorg/promptbook
|
|
6917
7714
|
`));
|
|
6918
7715
|
});
|
|
6919
|
-
|
|
6920
|
-
* @swagger
|
|
6921
|
-
*
|
|
6922
|
-
* /login:
|
|
6923
|
-
* post:
|
|
6924
|
-
* summary: Login to the server
|
|
6925
|
-
* description: Login to the server and get identification.
|
|
6926
|
-
* requestBody:
|
|
6927
|
-
* required: true
|
|
6928
|
-
* content:
|
|
6929
|
-
* application/json:
|
|
6930
|
-
* schema:
|
|
6931
|
-
* type: object
|
|
6932
|
-
* properties:
|
|
6933
|
-
* username:
|
|
6934
|
-
* type: string
|
|
6935
|
-
* password:
|
|
6936
|
-
* type: string
|
|
6937
|
-
* appId:
|
|
6938
|
-
* type: string
|
|
6939
|
-
* responses:
|
|
6940
|
-
* 200:
|
|
6941
|
-
* description: Successful login
|
|
6942
|
-
* content:
|
|
6943
|
-
* application/json:
|
|
6944
|
-
* schema:
|
|
6945
|
-
* type: object
|
|
6946
|
-
* properties:
|
|
6947
|
-
* identification:
|
|
6948
|
-
* type: object
|
|
6949
|
-
*/
|
|
6950
|
-
app.post([`/login`, `${rootPath}/login`], async (request, response) => {
|
|
7716
|
+
app.post(`/login`, async (request, response) => {
|
|
6951
7717
|
if (!isApplicationModeAllowed || login === null) {
|
|
6952
7718
|
response.status(400).send('Application mode is not allowed');
|
|
6953
7719
|
return;
|
|
@@ -6972,9 +7738,7 @@ function startRemoteServer(options) {
|
|
|
6972
7738
|
return;
|
|
6973
7739
|
}
|
|
6974
7740
|
catch (error) {
|
|
6975
|
-
|
|
6976
|
-
throw error;
|
|
6977
|
-
}
|
|
7741
|
+
assertsError(error);
|
|
6978
7742
|
if (error instanceof AuthenticationError) {
|
|
6979
7743
|
response.status(401).send({
|
|
6980
7744
|
isSuccess: false,
|
|
@@ -6989,23 +7753,7 @@ function startRemoteServer(options) {
|
|
|
6989
7753
|
response.status(400).send({ error: serializeError(error) });
|
|
6990
7754
|
}
|
|
6991
7755
|
});
|
|
6992
|
-
|
|
6993
|
-
* @swagger
|
|
6994
|
-
* /books:
|
|
6995
|
-
* get:
|
|
6996
|
-
* summary: List all books
|
|
6997
|
-
* description: Returns a list of all available books in the collection.
|
|
6998
|
-
* responses:
|
|
6999
|
-
* 200:
|
|
7000
|
-
* description: A list of books.
|
|
7001
|
-
* content:
|
|
7002
|
-
* application/json:
|
|
7003
|
-
* schema:
|
|
7004
|
-
* type: array
|
|
7005
|
-
* items:
|
|
7006
|
-
* type: string
|
|
7007
|
-
*/
|
|
7008
|
-
app.get([`/books`, `${rootPath}/books`], async (request, response) => {
|
|
7756
|
+
app.get(`/books`, async (request, response) => {
|
|
7009
7757
|
if (collection === null) {
|
|
7010
7758
|
response.status(500).send('No collection available');
|
|
7011
7759
|
return;
|
|
@@ -7015,30 +7763,7 @@ function startRemoteServer(options) {
|
|
|
7015
7763
|
response.send(pipelines);
|
|
7016
7764
|
});
|
|
7017
7765
|
// TODO: [๐ง ] Is it secure / good idea to expose source codes of hosted books
|
|
7018
|
-
|
|
7019
|
-
* @swagger
|
|
7020
|
-
* /books/{bookId}:
|
|
7021
|
-
* get:
|
|
7022
|
-
* summary: Get book content
|
|
7023
|
-
* description: Returns the content of a specific book.
|
|
7024
|
-
* parameters:
|
|
7025
|
-
* - in: path
|
|
7026
|
-
* name: bookId
|
|
7027
|
-
* required: true
|
|
7028
|
-
* schema:
|
|
7029
|
-
* type: string
|
|
7030
|
-
* description: The ID of the book to retrieve.
|
|
7031
|
-
* responses:
|
|
7032
|
-
* 200:
|
|
7033
|
-
* description: The content of the book.
|
|
7034
|
-
* content:
|
|
7035
|
-
* text/markdown:
|
|
7036
|
-
* schema:
|
|
7037
|
-
* type: string
|
|
7038
|
-
* 404:
|
|
7039
|
-
* description: Book not found.
|
|
7040
|
-
*/
|
|
7041
|
-
app.get([`/books/*`, `${rootPath}/books/*`], async (request, response) => {
|
|
7766
|
+
app.get(`/books/*`, async (request, response) => {
|
|
7042
7767
|
try {
|
|
7043
7768
|
if (collection === null) {
|
|
7044
7769
|
response.status(500).send('No collection nor books available');
|
|
@@ -7057,9 +7782,7 @@ function startRemoteServer(options) {
|
|
|
7057
7782
|
.send(source.content);
|
|
7058
7783
|
}
|
|
7059
7784
|
catch (error) {
|
|
7060
|
-
|
|
7061
|
-
throw error;
|
|
7062
|
-
}
|
|
7785
|
+
assertsError(error);
|
|
7063
7786
|
response
|
|
7064
7787
|
.status(404)
|
|
7065
7788
|
.send({ error: serializeError(error) });
|
|
@@ -7092,26 +7815,10 @@ function startRemoteServer(options) {
|
|
|
7092
7815
|
};
|
|
7093
7816
|
}
|
|
7094
7817
|
}
|
|
7095
|
-
|
|
7096
|
-
|
|
7097
|
-
* /executions:
|
|
7098
|
-
* get:
|
|
7099
|
-
* summary: List all executions
|
|
7100
|
-
* description: Returns a list of all running execution tasks.
|
|
7101
|
-
* responses:
|
|
7102
|
-
* 200:
|
|
7103
|
-
* description: A list of execution tasks.
|
|
7104
|
-
* content:
|
|
7105
|
-
* application/json:
|
|
7106
|
-
* schema:
|
|
7107
|
-
* type: array
|
|
7108
|
-
* items:
|
|
7109
|
-
* type: object
|
|
7110
|
-
*/
|
|
7111
|
-
app.get([`/executions`, `${rootPath}/executions`], async (request, response) => {
|
|
7112
|
-
response.send(runningExecutionTasks.map((runningExecutionTask) => exportExecutionTask(runningExecutionTask, false)));
|
|
7818
|
+
app.get(`/executions`, async (request, response) => {
|
|
7819
|
+
response.send(runningExecutionTasks.map((runningExecutionTask) => exportExecutionTask(runningExecutionTask, false)) /* <- TODO: satisfies paths['/executions']['get']['responses']['200']['content']['application/json'] */);
|
|
7113
7820
|
});
|
|
7114
|
-
app.get(
|
|
7821
|
+
app.get(`/executions/last`, async (request, response) => {
|
|
7115
7822
|
// TODO: [๐คฌ] Filter only for user
|
|
7116
7823
|
if (runningExecutionTasks.length === 0) {
|
|
7117
7824
|
response.status(404).send('No execution tasks found');
|
|
@@ -7120,7 +7827,7 @@ function startRemoteServer(options) {
|
|
|
7120
7827
|
const lastExecutionTask = runningExecutionTasks[runningExecutionTasks.length - 1];
|
|
7121
7828
|
response.send(exportExecutionTask(lastExecutionTask, true));
|
|
7122
7829
|
});
|
|
7123
|
-
app.get(
|
|
7830
|
+
app.get(`/executions/:taskId`, async (request, response) => {
|
|
7124
7831
|
const { taskId } = request.params;
|
|
7125
7832
|
// TODO: [๐คฌ] Filter only for user
|
|
7126
7833
|
const executionTask = runningExecutionTasks.find((executionTask) => executionTask.taskId === taskId);
|
|
@@ -7132,39 +7839,12 @@ function startRemoteServer(options) {
|
|
|
7132
7839
|
}
|
|
7133
7840
|
response.send(exportExecutionTask(executionTask, true));
|
|
7134
7841
|
});
|
|
7135
|
-
|
|
7136
|
-
* @swagger
|
|
7137
|
-
* /executions/new:
|
|
7138
|
-
* post:
|
|
7139
|
-
* summary: Start a new execution
|
|
7140
|
-
* description: Starts a new execution task for a given pipeline.
|
|
7141
|
-
* requestBody:
|
|
7142
|
-
* required: true
|
|
7143
|
-
* content:
|
|
7144
|
-
* application/json:
|
|
7145
|
-
* schema:
|
|
7146
|
-
* type: object
|
|
7147
|
-
* properties:
|
|
7148
|
-
* pipelineUrl:
|
|
7149
|
-
* type: string
|
|
7150
|
-
* inputParameters:
|
|
7151
|
-
* type: object
|
|
7152
|
-
* identification:
|
|
7153
|
-
* type: object
|
|
7154
|
-
* responses:
|
|
7155
|
-
* 200:
|
|
7156
|
-
* description: The newly created execution task.
|
|
7157
|
-
* content:
|
|
7158
|
-
* application/json:
|
|
7159
|
-
* schema:
|
|
7160
|
-
* type: object
|
|
7161
|
-
* 400:
|
|
7162
|
-
* description: Invalid input.
|
|
7163
|
-
*/
|
|
7164
|
-
app.post([`/executions/new`, `${rootPath}/executions/new`], async (request, response) => {
|
|
7842
|
+
app.post(`/executions/new`, async (request, response) => {
|
|
7165
7843
|
try {
|
|
7166
7844
|
const { inputParameters, identification /* <- [๐คฌ] */ } = request.body;
|
|
7167
|
-
const pipelineUrl = request.body
|
|
7845
|
+
const pipelineUrl = request.body
|
|
7846
|
+
.pipelineUrl /* <- TODO: as paths['/executions/new']['post']['requestBody']['content']['application/json'] */ ||
|
|
7847
|
+
request.body.book;
|
|
7168
7848
|
// TODO: [๐ง ] Check `pipelineUrl` and `inputParameters` here or it should be responsibility of `collection.getPipelineByUrl` and `pipelineExecutor`
|
|
7169
7849
|
const pipeline = await (collection === null || collection === void 0 ? void 0 : collection.getPipelineByUrl(pipelineUrl));
|
|
7170
7850
|
if (pipeline === undefined) {
|
|
@@ -7178,7 +7858,7 @@ function startRemoteServer(options) {
|
|
|
7178
7858
|
await forTime(10);
|
|
7179
7859
|
// <- Note: Wait for a while to wait for quick responses or sudden but asynchronous errors
|
|
7180
7860
|
// <- TODO: Put this into configuration
|
|
7181
|
-
response.send(executionTask);
|
|
7861
|
+
response.send(executionTask /* <- TODO: satisfies paths['/executions/new']['post']['responses']['200']['content']['application/json'] */);
|
|
7182
7862
|
/*/
|
|
7183
7863
|
executionTask.asObservable().subscribe({
|
|
7184
7864
|
next(partialResult) {
|
|
@@ -7198,19 +7878,24 @@ function startRemoteServer(options) {
|
|
|
7198
7878
|
*/
|
|
7199
7879
|
}
|
|
7200
7880
|
catch (error) {
|
|
7201
|
-
|
|
7202
|
-
throw error;
|
|
7203
|
-
}
|
|
7881
|
+
assertsError(error);
|
|
7204
7882
|
response.status(400).send({ error: serializeError(error) });
|
|
7205
7883
|
}
|
|
7206
7884
|
});
|
|
7885
|
+
/**
|
|
7886
|
+
* Catch-all handler for unmatched routes
|
|
7887
|
+
*/
|
|
7888
|
+
app.use((request, response) => {
|
|
7889
|
+
response.status(404).send(`URL "${request.originalUrl}" was not found on Promptbook server.`);
|
|
7890
|
+
});
|
|
7207
7891
|
const httpServer = http.createServer(app);
|
|
7208
7892
|
const server = new Server(httpServer, {
|
|
7209
|
-
path:
|
|
7210
|
-
transports: [
|
|
7893
|
+
path: '/socket.io',
|
|
7894
|
+
transports: ['polling', 'websocket' /*, <- TODO: [๐ฌ] Allow to pass `transports`, add 'webtransport' */],
|
|
7211
7895
|
cors: {
|
|
7212
7896
|
origin: '*',
|
|
7213
7897
|
methods: ['GET', 'POST'],
|
|
7898
|
+
// <- TODO: [๐ก] Allow to pass
|
|
7214
7899
|
},
|
|
7215
7900
|
});
|
|
7216
7901
|
server.on('connection', (socket) => {
|
|
@@ -7264,9 +7949,7 @@ function startRemoteServer(options) {
|
|
|
7264
7949
|
socket.emit('prompt-response', { promptResult } /* <- Note: [๐ค] */);
|
|
7265
7950
|
}
|
|
7266
7951
|
catch (error) {
|
|
7267
|
-
|
|
7268
|
-
throw error;
|
|
7269
|
-
}
|
|
7952
|
+
assertsError(error);
|
|
7270
7953
|
socket.emit('error', serializeError(error) /* <- Note: [๐ค] */);
|
|
7271
7954
|
}
|
|
7272
7955
|
finally {
|
|
@@ -7288,9 +7971,7 @@ function startRemoteServer(options) {
|
|
|
7288
7971
|
socket.emit('listModels-response', { models } /* <- Note: [๐ค] */);
|
|
7289
7972
|
}
|
|
7290
7973
|
catch (error) {
|
|
7291
|
-
|
|
7292
|
-
throw error;
|
|
7293
|
-
}
|
|
7974
|
+
assertsError(error);
|
|
7294
7975
|
socket.emit('error', serializeError(error));
|
|
7295
7976
|
}
|
|
7296
7977
|
finally {
|
|
@@ -7311,9 +7992,7 @@ function startRemoteServer(options) {
|
|
|
7311
7992
|
socket.emit('preparePipeline-response', { preparedPipeline } /* <- Note: [๐ค] */);
|
|
7312
7993
|
}
|
|
7313
7994
|
catch (error) {
|
|
7314
|
-
|
|
7315
|
-
throw error;
|
|
7316
|
-
}
|
|
7995
|
+
assertsError(error);
|
|
7317
7996
|
socket.emit('error', serializeError(error));
|
|
7318
7997
|
// <- TODO: [๐] There is a problem with the remote server handling errors and sending them back to the client
|
|
7319
7998
|
}
|
|
@@ -7361,8 +8040,7 @@ function startRemoteServer(options) {
|
|
|
7361
8040
|
};
|
|
7362
8041
|
}
|
|
7363
8042
|
/**
|
|
7364
|
-
* TODO:
|
|
7365
|
-
* TODO: [๐ฉ๐พโ๐คโ๐ง๐พ] Allow to pass custom fetch function here - PromptbookFetch
|
|
8043
|
+
* TODO: [๐ก] Add CORS and security - probbably via `helmet`
|
|
7366
8044
|
* TODO: Split this file into multiple functions - handler for each request
|
|
7367
8045
|
* TODO: Maybe use `$exportJson`
|
|
7368
8046
|
* TODO: [๐ง ][๐] Maybe not `isAnonymous: boolean` BUT `mode: 'ANONYMOUS'|'COLLECTION'`
|