@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/umd/index.umd.js
CHANGED
|
@@ -1,16 +1,34 @@
|
|
|
1
1
|
(function (global, factory) {
|
|
2
|
-
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('colors'), require('express'), require('http'), require('socket.io'), require('spacetrim'), require('
|
|
3
|
-
typeof define === 'function' && define.amd ? define(['exports', 'colors', 'express', 'http', 'socket.io', 'spacetrim', '
|
|
4
|
-
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global["promptbook-remote-server"] = {}, global.colors, global.express, global.http, global.socket_io, global.spaceTrim, global.
|
|
5
|
-
})(this, (function (exports, colors, express, http, socket_io, spaceTrim,
|
|
2
|
+
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('colors'), require('express'), require('http'), require('socket.io'), require('spacetrim'), require('express-openapi-validator'), require('swagger-ui-express'), require('waitasecond'), require('crypto'), require('child_process'), require('fs/promises'), require('path'), require('rxjs'), require('prettier'), require('prettier/parser-html'), require('crypto-js/enc-hex'), require('crypto-js/sha256'), require('crypto-js'), require('mime-types'), require('papaparse')) :
|
|
3
|
+
typeof define === 'function' && define.amd ? define(['exports', 'colors', 'express', 'http', 'socket.io', 'spacetrim', 'express-openapi-validator', 'swagger-ui-express', 'waitasecond', 'crypto', 'child_process', 'fs/promises', 'path', 'rxjs', 'prettier', 'prettier/parser-html', 'crypto-js/enc-hex', 'crypto-js/sha256', 'crypto-js', 'mime-types', 'papaparse'], factory) :
|
|
4
|
+
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global["promptbook-remote-server"] = {}, global.colors, global.express, global.http, global.socket_io, global.spaceTrim, global.OpenApiValidator, global.swaggerUi, global.waitasecond, global.crypto, global.child_process, global.promises, global.path, global.rxjs, global.prettier, global.parserHtml, global.hexEncoder, global.sha256, global.cryptoJs, global.mimeTypes, global.papaparse));
|
|
5
|
+
})(this, (function (exports, colors, express, http, socket_io, spaceTrim, OpenApiValidator, swaggerUi, waitasecond, crypto, child_process, promises, path, rxjs, prettier, parserHtml, hexEncoder, sha256, cryptoJs, mimeTypes, papaparse) { 'use strict';
|
|
6
6
|
|
|
7
7
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
8
8
|
|
|
9
|
+
function _interopNamespace(e) {
|
|
10
|
+
if (e && e.__esModule) return e;
|
|
11
|
+
var n = Object.create(null);
|
|
12
|
+
if (e) {
|
|
13
|
+
Object.keys(e).forEach(function (k) {
|
|
14
|
+
if (k !== 'default') {
|
|
15
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
16
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
17
|
+
enumerable: true,
|
|
18
|
+
get: function () { return e[k]; }
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
n["default"] = e;
|
|
24
|
+
return Object.freeze(n);
|
|
25
|
+
}
|
|
26
|
+
|
|
9
27
|
var colors__default = /*#__PURE__*/_interopDefaultLegacy(colors);
|
|
10
28
|
var express__default = /*#__PURE__*/_interopDefaultLegacy(express);
|
|
11
29
|
var http__default = /*#__PURE__*/_interopDefaultLegacy(http);
|
|
12
30
|
var spaceTrim__default = /*#__PURE__*/_interopDefaultLegacy(spaceTrim);
|
|
13
|
-
var
|
|
31
|
+
var OpenApiValidator__namespace = /*#__PURE__*/_interopNamespace(OpenApiValidator);
|
|
14
32
|
var swaggerUi__default = /*#__PURE__*/_interopDefaultLegacy(swaggerUi);
|
|
15
33
|
var parserHtml__default = /*#__PURE__*/_interopDefaultLegacy(parserHtml);
|
|
16
34
|
var hexEncoder__default = /*#__PURE__*/_interopDefaultLegacy(hexEncoder);
|
|
@@ -30,7 +48,7 @@
|
|
|
30
48
|
* @generated
|
|
31
49
|
* @see https://github.com/webgptorg/promptbook
|
|
32
50
|
*/
|
|
33
|
-
const PROMPTBOOK_ENGINE_VERSION = '0.
|
|
51
|
+
const PROMPTBOOK_ENGINE_VERSION = '0.92.0-10';
|
|
34
52
|
/**
|
|
35
53
|
* TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
|
|
36
54
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
@@ -84,6 +102,7 @@
|
|
|
84
102
|
* @public exported from `@promptbook/core`
|
|
85
103
|
*/
|
|
86
104
|
const CLAIM = `It's time for a paradigm shift. The future of software in plain English, French or Latin`;
|
|
105
|
+
// <- TODO: [🐊] Pick the best claim
|
|
87
106
|
/**
|
|
88
107
|
* When the title is not provided, the default title is used
|
|
89
108
|
*
|
|
@@ -116,6 +135,7 @@
|
|
|
116
135
|
infinity: '(infinity; ∞)',
|
|
117
136
|
negativeInfinity: '(negative infinity; -∞)',
|
|
118
137
|
unserializable: '(unserializable value)',
|
|
138
|
+
circular: '(circular JSON)',
|
|
119
139
|
};
|
|
120
140
|
/**
|
|
121
141
|
* Small number limit
|
|
@@ -155,7 +175,7 @@
|
|
|
155
175
|
*/
|
|
156
176
|
const DEFAULT_MAX_EXECUTION_ATTEMPTS = 10; // <- TODO: [🤹♂️]
|
|
157
177
|
// <- TODO: [🕝] Make also `BOOKS_DIRNAME_ALTERNATIVES`
|
|
158
|
-
// TODO:
|
|
178
|
+
// TODO: Just `.promptbook` in config, hardcode subfolders like `download-cache` or `execution-cache`
|
|
159
179
|
/**
|
|
160
180
|
* Where to store the temporary downloads
|
|
161
181
|
*
|
|
@@ -210,6 +230,122 @@
|
|
|
210
230
|
* TODO: [🧠][🧜♂️] Maybe join remoteServerUrl and path into single value
|
|
211
231
|
*/
|
|
212
232
|
|
|
233
|
+
/**
|
|
234
|
+
* Make error report URL for the given error
|
|
235
|
+
*
|
|
236
|
+
* @private private within the repository
|
|
237
|
+
*/
|
|
238
|
+
function getErrorReportUrl(error) {
|
|
239
|
+
const report = {
|
|
240
|
+
title: `🐜 Error report from ${NAME}`,
|
|
241
|
+
body: spaceTrim__default["default"]((block) => `
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
\`${error.name || 'Error'}\` has occurred in the [${NAME}], please look into it @${ADMIN_GITHUB_NAME}.
|
|
245
|
+
|
|
246
|
+
\`\`\`
|
|
247
|
+
${block(error.message || '(no error message)')}
|
|
248
|
+
\`\`\`
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
## More info:
|
|
252
|
+
|
|
253
|
+
- **Promptbook engine version:** ${PROMPTBOOK_ENGINE_VERSION}
|
|
254
|
+
- **Book language version:** ${BOOK_LANGUAGE_VERSION}
|
|
255
|
+
- **Time:** ${new Date().toISOString()}
|
|
256
|
+
|
|
257
|
+
<details>
|
|
258
|
+
<summary>Stack trace:</summary>
|
|
259
|
+
|
|
260
|
+
## Stack trace:
|
|
261
|
+
|
|
262
|
+
\`\`\`stacktrace
|
|
263
|
+
${block(error.stack || '(empty)')}
|
|
264
|
+
\`\`\`
|
|
265
|
+
</details>
|
|
266
|
+
|
|
267
|
+
`),
|
|
268
|
+
};
|
|
269
|
+
const reportUrl = new URL(`https://github.com/webgptorg/promptbook/issues/new`);
|
|
270
|
+
reportUrl.searchParams.set('labels', 'bug');
|
|
271
|
+
reportUrl.searchParams.set('assignees', ADMIN_GITHUB_NAME);
|
|
272
|
+
reportUrl.searchParams.set('title', report.title);
|
|
273
|
+
reportUrl.searchParams.set('body', report.body);
|
|
274
|
+
return reportUrl;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* This error type indicates that the error should not happen and its last check before crashing with some other error
|
|
279
|
+
*
|
|
280
|
+
* @public exported from `@promptbook/core`
|
|
281
|
+
*/
|
|
282
|
+
class UnexpectedError extends Error {
|
|
283
|
+
constructor(message) {
|
|
284
|
+
super(spaceTrim.spaceTrim((block) => `
|
|
285
|
+
${block(message)}
|
|
286
|
+
|
|
287
|
+
Note: This error should not happen.
|
|
288
|
+
It's probbably a bug in the pipeline collection
|
|
289
|
+
|
|
290
|
+
Please report issue:
|
|
291
|
+
${block(getErrorReportUrl(new Error(message)).href)}
|
|
292
|
+
|
|
293
|
+
Or contact us on ${ADMIN_EMAIL}
|
|
294
|
+
|
|
295
|
+
`));
|
|
296
|
+
this.name = 'UnexpectedError';
|
|
297
|
+
Object.setPrototypeOf(this, UnexpectedError.prototype);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* This error type indicates that somewhere in the code non-Error object was thrown and it was wrapped into the `WrappedError`
|
|
303
|
+
*
|
|
304
|
+
* @public exported from `@promptbook/core`
|
|
305
|
+
*/
|
|
306
|
+
class WrappedError extends Error {
|
|
307
|
+
constructor(whatWasThrown) {
|
|
308
|
+
const tag = `[🤮]`;
|
|
309
|
+
console.error(tag, whatWasThrown);
|
|
310
|
+
super(spaceTrim.spaceTrim(`
|
|
311
|
+
Non-Error object was thrown
|
|
312
|
+
|
|
313
|
+
Note: Look for ${tag} in the console for more details
|
|
314
|
+
Please report issue on ${ADMIN_EMAIL}
|
|
315
|
+
`));
|
|
316
|
+
this.name = 'WrappedError';
|
|
317
|
+
Object.setPrototypeOf(this, WrappedError.prototype);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* Helper used in catch blocks to assert that the error is an instance of `Error`
|
|
323
|
+
*
|
|
324
|
+
* @param whatWasThrown Any object that was thrown
|
|
325
|
+
* @returns Nothing if the error is an instance of `Error`
|
|
326
|
+
* @throws `WrappedError` or `UnexpectedError` if the error is not standard
|
|
327
|
+
*
|
|
328
|
+
* @private within the repository
|
|
329
|
+
*/
|
|
330
|
+
function assertsError(whatWasThrown) {
|
|
331
|
+
// Case 1: Handle error which was rethrown as `WrappedError`
|
|
332
|
+
if (whatWasThrown instanceof WrappedError) {
|
|
333
|
+
const wrappedError = whatWasThrown;
|
|
334
|
+
throw wrappedError;
|
|
335
|
+
}
|
|
336
|
+
// Case 2: Handle unexpected errors
|
|
337
|
+
if (whatWasThrown instanceof UnexpectedError) {
|
|
338
|
+
const unexpectedError = whatWasThrown;
|
|
339
|
+
throw unexpectedError;
|
|
340
|
+
}
|
|
341
|
+
// Case 3: Handle standard errors - keep them up to consumer
|
|
342
|
+
if (whatWasThrown instanceof Error) {
|
|
343
|
+
return;
|
|
344
|
+
}
|
|
345
|
+
// Case 4: Handle non-standard errors - wrap them into `WrappedError` and throw
|
|
346
|
+
throw new WrappedError(whatWasThrown);
|
|
347
|
+
}
|
|
348
|
+
|
|
213
349
|
/**
|
|
214
350
|
* AuthenticationError is thrown from login function which is dependency of remote server
|
|
215
351
|
*
|
|
@@ -254,7 +390,7 @@
|
|
|
254
390
|
}
|
|
255
391
|
}
|
|
256
392
|
/**
|
|
257
|
-
* TODO:
|
|
393
|
+
* TODO: [🧠][🌂] Add id to all errors
|
|
258
394
|
*/
|
|
259
395
|
|
|
260
396
|
/**
|
|
@@ -464,74 +600,6 @@
|
|
|
464
600
|
}
|
|
465
601
|
}
|
|
466
602
|
|
|
467
|
-
/**
|
|
468
|
-
* Make error report URL for the given error
|
|
469
|
-
*
|
|
470
|
-
* @private private within the repository
|
|
471
|
-
*/
|
|
472
|
-
function getErrorReportUrl(error) {
|
|
473
|
-
const report = {
|
|
474
|
-
title: `🐜 Error report from ${NAME}`,
|
|
475
|
-
body: spaceTrim__default["default"]((block) => `
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
\`${error.name || 'Error'}\` has occurred in the [${NAME}], please look into it @${ADMIN_GITHUB_NAME}.
|
|
479
|
-
|
|
480
|
-
\`\`\`
|
|
481
|
-
${block(error.message || '(no error message)')}
|
|
482
|
-
\`\`\`
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
## More info:
|
|
486
|
-
|
|
487
|
-
- **Promptbook engine version:** ${PROMPTBOOK_ENGINE_VERSION}
|
|
488
|
-
- **Book language version:** ${BOOK_LANGUAGE_VERSION}
|
|
489
|
-
- **Time:** ${new Date().toISOString()}
|
|
490
|
-
|
|
491
|
-
<details>
|
|
492
|
-
<summary>Stack trace:</summary>
|
|
493
|
-
|
|
494
|
-
## Stack trace:
|
|
495
|
-
|
|
496
|
-
\`\`\`stacktrace
|
|
497
|
-
${block(error.stack || '(empty)')}
|
|
498
|
-
\`\`\`
|
|
499
|
-
</details>
|
|
500
|
-
|
|
501
|
-
`),
|
|
502
|
-
};
|
|
503
|
-
const reportUrl = new URL(`https://github.com/webgptorg/promptbook/issues/new`);
|
|
504
|
-
reportUrl.searchParams.set('labels', 'bug');
|
|
505
|
-
reportUrl.searchParams.set('assignees', ADMIN_GITHUB_NAME);
|
|
506
|
-
reportUrl.searchParams.set('title', report.title);
|
|
507
|
-
reportUrl.searchParams.set('body', report.body);
|
|
508
|
-
return reportUrl;
|
|
509
|
-
}
|
|
510
|
-
|
|
511
|
-
/**
|
|
512
|
-
* This error type indicates that the error should not happen and its last check before crashing with some other error
|
|
513
|
-
*
|
|
514
|
-
* @public exported from `@promptbook/core`
|
|
515
|
-
*/
|
|
516
|
-
class UnexpectedError extends Error {
|
|
517
|
-
constructor(message) {
|
|
518
|
-
super(spaceTrim.spaceTrim((block) => `
|
|
519
|
-
${block(message)}
|
|
520
|
-
|
|
521
|
-
Note: This error should not happen.
|
|
522
|
-
It's probbably a bug in the pipeline collection
|
|
523
|
-
|
|
524
|
-
Please report issue:
|
|
525
|
-
${block(getErrorReportUrl(new Error(message)).href)}
|
|
526
|
-
|
|
527
|
-
Or contact us on ${ADMIN_EMAIL}
|
|
528
|
-
|
|
529
|
-
`));
|
|
530
|
-
this.name = 'UnexpectedError';
|
|
531
|
-
Object.setPrototypeOf(this, UnexpectedError.prototype);
|
|
532
|
-
}
|
|
533
|
-
}
|
|
534
|
-
|
|
535
603
|
/**
|
|
536
604
|
* Index of all custom errors
|
|
537
605
|
*
|
|
@@ -552,7 +620,10 @@
|
|
|
552
620
|
PipelineExecutionError,
|
|
553
621
|
PipelineLogicError,
|
|
554
622
|
PipelineUrlError,
|
|
623
|
+
AuthenticationError,
|
|
624
|
+
PromptbookFetchError,
|
|
555
625
|
UnexpectedError,
|
|
626
|
+
WrappedError,
|
|
556
627
|
// TODO: [🪑]> VersionMismatchError,
|
|
557
628
|
};
|
|
558
629
|
/**
|
|
@@ -569,8 +640,6 @@
|
|
|
569
640
|
TypeError,
|
|
570
641
|
URIError,
|
|
571
642
|
AggregateError,
|
|
572
|
-
AuthenticationError,
|
|
573
|
-
PromptbookFetchError,
|
|
574
643
|
/*
|
|
575
644
|
Note: Not widely supported
|
|
576
645
|
> InternalError,
|
|
@@ -813,9 +882,7 @@
|
|
|
813
882
|
return result.trim();
|
|
814
883
|
}
|
|
815
884
|
catch (error) {
|
|
816
|
-
|
|
817
|
-
throw error;
|
|
818
|
-
}
|
|
885
|
+
assertsError(error);
|
|
819
886
|
return null;
|
|
820
887
|
}
|
|
821
888
|
}
|
|
@@ -893,9 +960,7 @@
|
|
|
893
960
|
return result.trim() + toExec;
|
|
894
961
|
}
|
|
895
962
|
catch (error) {
|
|
896
|
-
|
|
897
|
-
throw error;
|
|
898
|
-
}
|
|
963
|
+
assertsError(error);
|
|
899
964
|
return null;
|
|
900
965
|
}
|
|
901
966
|
}
|
|
@@ -926,9 +991,7 @@
|
|
|
926
991
|
throw new Error(`Can not locate app ${appName} on Windows.`);
|
|
927
992
|
}
|
|
928
993
|
catch (error) {
|
|
929
|
-
|
|
930
|
-
throw error;
|
|
931
|
-
}
|
|
994
|
+
assertsError(error);
|
|
932
995
|
return null;
|
|
933
996
|
}
|
|
934
997
|
}
|
|
@@ -1166,9 +1229,7 @@
|
|
|
1166
1229
|
JSON.stringify(value); // <- TODO: [0]
|
|
1167
1230
|
}
|
|
1168
1231
|
catch (error) {
|
|
1169
|
-
|
|
1170
|
-
throw error;
|
|
1171
|
-
}
|
|
1232
|
+
assertsError(error);
|
|
1172
1233
|
throw new UnexpectedError(spaceTrim__default["default"]((block) => `
|
|
1173
1234
|
\`${name}\` is not serializable
|
|
1174
1235
|
|
|
@@ -1741,7 +1802,7 @@
|
|
|
1741
1802
|
if (pipeline.title === undefined || pipeline.title === '' || pipeline.title === DEFAULT_BOOK_TITLE) {
|
|
1742
1803
|
return false;
|
|
1743
1804
|
}
|
|
1744
|
-
if (!pipeline.personas.every((persona) => persona.
|
|
1805
|
+
if (!pipeline.personas.every((persona) => persona.modelsRequirements !== undefined)) {
|
|
1745
1806
|
return false;
|
|
1746
1807
|
}
|
|
1747
1808
|
if (!pipeline.knowledgeSources.every((knowledgeSource) => knowledgeSource.preparationIds !== undefined)) {
|
|
@@ -1768,6 +1829,9 @@
|
|
|
1768
1829
|
/**
|
|
1769
1830
|
* Function isValidJsonString will tell you if the string is valid JSON or not
|
|
1770
1831
|
*
|
|
1832
|
+
* @param value The string to check
|
|
1833
|
+
* @returns True if the string is a valid JSON string, false otherwise
|
|
1834
|
+
*
|
|
1771
1835
|
* @public exported from `@promptbook/utils`
|
|
1772
1836
|
*/
|
|
1773
1837
|
function isValidJsonString(value /* <- [👨⚖️] */) {
|
|
@@ -1776,9 +1840,7 @@
|
|
|
1776
1840
|
return true;
|
|
1777
1841
|
}
|
|
1778
1842
|
catch (error) {
|
|
1779
|
-
|
|
1780
|
-
throw error;
|
|
1781
|
-
}
|
|
1843
|
+
assertsError(error);
|
|
1782
1844
|
if (error.message.includes('Unexpected token')) {
|
|
1783
1845
|
return false;
|
|
1784
1846
|
}
|
|
@@ -1786,6 +1848,45 @@
|
|
|
1786
1848
|
}
|
|
1787
1849
|
}
|
|
1788
1850
|
|
|
1851
|
+
/**
|
|
1852
|
+
* Converts a JavaScript Object Notation (JSON) string into an object.
|
|
1853
|
+
*
|
|
1854
|
+
* Note: This is wrapper around `JSON.parse()` with better error and type handling
|
|
1855
|
+
*
|
|
1856
|
+
* @public exported from `@promptbook/utils`
|
|
1857
|
+
*/
|
|
1858
|
+
function jsonParse(value) {
|
|
1859
|
+
if (value === undefined) {
|
|
1860
|
+
throw new Error(`Can not parse JSON from undefined value.`);
|
|
1861
|
+
}
|
|
1862
|
+
else if (typeof value !== 'string') {
|
|
1863
|
+
console.error('Can not parse JSON from non-string value.', { text: value });
|
|
1864
|
+
throw new Error(spaceTrim__default["default"](`
|
|
1865
|
+
Can not parse JSON from non-string value.
|
|
1866
|
+
|
|
1867
|
+
The value type: ${typeof value}
|
|
1868
|
+
See more in console.
|
|
1869
|
+
`));
|
|
1870
|
+
}
|
|
1871
|
+
try {
|
|
1872
|
+
return JSON.parse(value);
|
|
1873
|
+
}
|
|
1874
|
+
catch (error) {
|
|
1875
|
+
if (!(error instanceof Error)) {
|
|
1876
|
+
throw error;
|
|
1877
|
+
}
|
|
1878
|
+
throw new Error(spaceTrim__default["default"]((block) => `
|
|
1879
|
+
${block(error.message)}
|
|
1880
|
+
|
|
1881
|
+
The JSON text:
|
|
1882
|
+
${block(value)}
|
|
1883
|
+
`));
|
|
1884
|
+
}
|
|
1885
|
+
}
|
|
1886
|
+
/**
|
|
1887
|
+
* TODO: !!!! Use in Promptbook.studio
|
|
1888
|
+
*/
|
|
1889
|
+
|
|
1789
1890
|
/**
|
|
1790
1891
|
* Recursively converts JSON strings to JSON objects
|
|
1791
1892
|
|
|
@@ -1804,7 +1905,7 @@
|
|
|
1804
1905
|
const newObject = { ...object };
|
|
1805
1906
|
for (const [key, value] of Object.entries(object)) {
|
|
1806
1907
|
if (typeof value === 'string' && isValidJsonString(value)) {
|
|
1807
|
-
newObject[key] =
|
|
1908
|
+
newObject[key] = jsonParse(value);
|
|
1808
1909
|
}
|
|
1809
1910
|
else {
|
|
1810
1911
|
newObject[key] = jsonStringsToJsons(value);
|
|
@@ -1916,8 +2017,8 @@
|
|
|
1916
2017
|
updatedAt = new Date();
|
|
1917
2018
|
errors.push(...executionResult.errors);
|
|
1918
2019
|
warnings.push(...executionResult.warnings);
|
|
1919
|
-
// <- TODO:
|
|
1920
|
-
// TODO: [🧠]
|
|
2020
|
+
// <- TODO: [🌂] Only unique errors and warnings should be added (or filtered)
|
|
2021
|
+
// TODO: [🧠] !! errors, warning, isSuccessful are redundant both in `ExecutionTask` and `ExecutionTask.currentValue`
|
|
1921
2022
|
// Also maybe move `ExecutionTask.currentValue.usage` -> `ExecutionTask.usage`
|
|
1922
2023
|
// And delete `ExecutionTask.currentValue.preparedPipeline`
|
|
1923
2024
|
assertsTaskSuccessful(executionResult);
|
|
@@ -1927,6 +2028,7 @@
|
|
|
1927
2028
|
partialResultSubject.next(executionResult);
|
|
1928
2029
|
}
|
|
1929
2030
|
catch (error) {
|
|
2031
|
+
assertsError(error);
|
|
1930
2032
|
status = 'ERROR';
|
|
1931
2033
|
errors.push(error);
|
|
1932
2034
|
partialResultSubject.error(error);
|
|
@@ -1980,7 +2082,7 @@
|
|
|
1980
2082
|
* TODO: [🐚] Split into more files and make `PrepareTask` & `RemoteTask` + split the function
|
|
1981
2083
|
*/
|
|
1982
2084
|
|
|
1983
|
-
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"}];
|
|
2085
|
+
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"}];
|
|
1984
2086
|
|
|
1985
2087
|
/**
|
|
1986
2088
|
* Checks if value is valid email
|
|
@@ -2283,7 +2385,7 @@
|
|
|
2283
2385
|
*/
|
|
2284
2386
|
function unpreparePipeline(pipeline) {
|
|
2285
2387
|
let { personas, knowledgeSources, tasks } = pipeline;
|
|
2286
|
-
personas = personas.map((persona) => ({ ...persona,
|
|
2388
|
+
personas = personas.map((persona) => ({ ...persona, modelsRequirements: undefined, preparationIds: undefined }));
|
|
2287
2389
|
knowledgeSources = knowledgeSources.map((knowledgeSource) => ({ ...knowledgeSource, preparationIds: undefined }));
|
|
2288
2390
|
tasks = tasks.map((task) => {
|
|
2289
2391
|
let { dependentParameterNames } = task;
|
|
@@ -2737,14 +2839,15 @@
|
|
|
2737
2839
|
}
|
|
2738
2840
|
}
|
|
2739
2841
|
catch (error) {
|
|
2740
|
-
|
|
2842
|
+
assertsError(error);
|
|
2843
|
+
if (error instanceof UnexpectedError) {
|
|
2741
2844
|
throw error;
|
|
2742
2845
|
}
|
|
2743
2846
|
errors.push({ llmExecutionTools, error });
|
|
2744
2847
|
}
|
|
2745
2848
|
}
|
|
2746
2849
|
if (errors.length === 1) {
|
|
2747
|
-
throw errors[0];
|
|
2850
|
+
throw errors[0].error;
|
|
2748
2851
|
}
|
|
2749
2852
|
else if (errors.length > 1) {
|
|
2750
2853
|
throw new PipelineExecutionError(
|
|
@@ -2870,27 +2973,48 @@
|
|
|
2870
2973
|
pipeline: await collection.getPipelineByUrl('https://promptbook.studio/promptbook/prepare-persona.book'),
|
|
2871
2974
|
tools,
|
|
2872
2975
|
});
|
|
2873
|
-
// TODO: [🚐] Make arrayable LLMs -> single LLM DRY
|
|
2874
2976
|
const _llms = arrayableToArray(tools.llm);
|
|
2875
2977
|
const llmTools = _llms.length === 1 ? _llms[0] : joinLlmExecutionTools(..._llms);
|
|
2876
|
-
const availableModels = await llmTools.listModels()
|
|
2877
|
-
const availableModelNames = availableModels
|
|
2978
|
+
const availableModels = (await llmTools.listModels())
|
|
2878
2979
|
.filter(({ modelVariant }) => modelVariant === 'CHAT')
|
|
2879
|
-
.map(({ modelName }) =>
|
|
2880
|
-
|
|
2881
|
-
|
|
2980
|
+
.map(({ modelName, modelDescription }) => ({
|
|
2981
|
+
modelName,
|
|
2982
|
+
modelDescription,
|
|
2983
|
+
// <- Note: `modelTitle` and `modelVariant` is not relevant for this task
|
|
2984
|
+
}));
|
|
2985
|
+
const result = await preparePersonaExecutor({
|
|
2986
|
+
availableModels /* <- Note: Passing as JSON */,
|
|
2987
|
+
personaDescription,
|
|
2988
|
+
}).asPromise();
|
|
2882
2989
|
const { outputParameters } = result;
|
|
2883
|
-
const {
|
|
2884
|
-
|
|
2990
|
+
const { modelsRequirements: modelsRequirementsJson } = outputParameters;
|
|
2991
|
+
let modelsRequirementsUnchecked = jsonParse(modelsRequirementsJson);
|
|
2885
2992
|
if (isVerbose) {
|
|
2886
|
-
console.info(`PERSONA ${personaDescription}`,
|
|
2993
|
+
console.info(`PERSONA ${personaDescription}`, modelsRequirementsUnchecked);
|
|
2887
2994
|
}
|
|
2888
|
-
|
|
2889
|
-
|
|
2995
|
+
if (!Array.isArray(modelsRequirementsUnchecked)) {
|
|
2996
|
+
// <- TODO: Book should have syntax and system to enforce shape of JSON
|
|
2997
|
+
modelsRequirementsUnchecked = [modelsRequirementsUnchecked];
|
|
2998
|
+
/*
|
|
2999
|
+
throw new UnexpectedError(
|
|
3000
|
+
spaceTrim(
|
|
3001
|
+
(block) => `
|
|
3002
|
+
Invalid \`modelsRequirements\`:
|
|
3003
|
+
|
|
3004
|
+
\`\`\`json
|
|
3005
|
+
${block(JSON.stringify(modelsRequirementsUnchecked, null, 4))}
|
|
3006
|
+
\`\`\`
|
|
3007
|
+
`,
|
|
3008
|
+
),
|
|
3009
|
+
);
|
|
3010
|
+
*/
|
|
3011
|
+
}
|
|
3012
|
+
const modelsRequirements = modelsRequirementsUnchecked.map((modelRequirements) => ({
|
|
2890
3013
|
modelVariant: 'CHAT',
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
3014
|
+
...modelRequirements,
|
|
3015
|
+
}));
|
|
3016
|
+
return {
|
|
3017
|
+
modelsRequirements,
|
|
2894
3018
|
};
|
|
2895
3019
|
}
|
|
2896
3020
|
/**
|
|
@@ -3585,9 +3709,7 @@
|
|
|
3585
3709
|
return await fetch(urlOrRequest, init);
|
|
3586
3710
|
}
|
|
3587
3711
|
catch (error) {
|
|
3588
|
-
|
|
3589
|
-
throw error;
|
|
3590
|
-
}
|
|
3712
|
+
assertsError(error);
|
|
3591
3713
|
let url;
|
|
3592
3714
|
if (typeof urlOrRequest === 'string') {
|
|
3593
3715
|
url = urlOrRequest;
|
|
@@ -3716,7 +3838,7 @@
|
|
|
3716
3838
|
> },
|
|
3717
3839
|
*/
|
|
3718
3840
|
async asJson() {
|
|
3719
|
-
return
|
|
3841
|
+
return jsonParse(await tools.fs.readFile(filename, 'utf-8'));
|
|
3720
3842
|
},
|
|
3721
3843
|
async asText() {
|
|
3722
3844
|
return await tools.fs.readFile(filename, 'utf-8');
|
|
@@ -3818,9 +3940,7 @@
|
|
|
3818
3940
|
knowledgePreparedUnflatten[index] = pieces;
|
|
3819
3941
|
}
|
|
3820
3942
|
catch (error) {
|
|
3821
|
-
|
|
3822
|
-
throw error;
|
|
3823
|
-
}
|
|
3943
|
+
assertsError(error);
|
|
3824
3944
|
console.warn(error);
|
|
3825
3945
|
// <- TODO: [🏮] Some standard way how to transform errors into warnings and how to handle non-critical fails during the tasks
|
|
3826
3946
|
}
|
|
@@ -3976,14 +4096,14 @@
|
|
|
3976
4096
|
// TODO: [🖌][🧠] Implement some `mapAsync` function
|
|
3977
4097
|
const preparedPersonas = new Array(personas.length);
|
|
3978
4098
|
await forEachAsync(personas, { maxParallelCount /* <- TODO: [🪂] When there are subtasks, this maximul limit can be broken */ }, async (persona, index) => {
|
|
3979
|
-
const
|
|
4099
|
+
const { modelsRequirements } = await preparePersona(persona.description, { ...tools, llm: llmToolsWithUsage }, {
|
|
3980
4100
|
rootDirname,
|
|
3981
4101
|
maxParallelCount /* <- TODO: [🪂] */,
|
|
3982
4102
|
isVerbose,
|
|
3983
4103
|
});
|
|
3984
4104
|
const preparedPersona = {
|
|
3985
4105
|
...persona,
|
|
3986
|
-
|
|
4106
|
+
modelsRequirements,
|
|
3987
4107
|
preparationIds: [/* TODO: [🧊] -> */ currentPreparation.id],
|
|
3988
4108
|
// <- TODO: [🍙] Make some standard order of json properties
|
|
3989
4109
|
};
|
|
@@ -4112,13 +4232,19 @@
|
|
|
4112
4232
|
return value.toISOString();
|
|
4113
4233
|
}
|
|
4114
4234
|
else {
|
|
4115
|
-
|
|
4235
|
+
try {
|
|
4236
|
+
return JSON.stringify(value);
|
|
4237
|
+
}
|
|
4238
|
+
catch (error) {
|
|
4239
|
+
if (error instanceof TypeError && error.message.includes('circular structure')) {
|
|
4240
|
+
return VALUE_STRINGS.circular;
|
|
4241
|
+
}
|
|
4242
|
+
throw error;
|
|
4243
|
+
}
|
|
4116
4244
|
}
|
|
4117
4245
|
}
|
|
4118
4246
|
catch (error) {
|
|
4119
|
-
|
|
4120
|
-
throw error;
|
|
4121
|
-
}
|
|
4247
|
+
assertsError(error);
|
|
4122
4248
|
console.error(error);
|
|
4123
4249
|
return VALUE_STRINGS.unserializable;
|
|
4124
4250
|
}
|
|
@@ -4175,9 +4301,7 @@
|
|
|
4175
4301
|
}
|
|
4176
4302
|
}
|
|
4177
4303
|
catch (error) {
|
|
4178
|
-
|
|
4179
|
-
throw error;
|
|
4180
|
-
}
|
|
4304
|
+
assertsError(error);
|
|
4181
4305
|
throw new ParseError(spaceTrim.spaceTrim((block) => `
|
|
4182
4306
|
Can not extract variables from the script
|
|
4183
4307
|
${block(error.stack || error.message)}
|
|
@@ -4296,6 +4420,46 @@
|
|
|
4296
4420
|
// encoding: 'utf-8',
|
|
4297
4421
|
});
|
|
4298
4422
|
|
|
4423
|
+
/**
|
|
4424
|
+
* Function to check if a string is valid CSV
|
|
4425
|
+
*
|
|
4426
|
+
* @param value The string to check
|
|
4427
|
+
* @returns True if the string is a valid CSV string, false otherwise
|
|
4428
|
+
*
|
|
4429
|
+
* @public exported from `@promptbook/utils`
|
|
4430
|
+
*/
|
|
4431
|
+
function isValidCsvString(value) {
|
|
4432
|
+
try {
|
|
4433
|
+
// A simple check for CSV format: at least one comma and no invalid characters
|
|
4434
|
+
if (value.includes(',') && /^[\w\s,"']+$/.test(value)) {
|
|
4435
|
+
return true;
|
|
4436
|
+
}
|
|
4437
|
+
return false;
|
|
4438
|
+
}
|
|
4439
|
+
catch (error) {
|
|
4440
|
+
assertsError(error);
|
|
4441
|
+
return false;
|
|
4442
|
+
}
|
|
4443
|
+
}
|
|
4444
|
+
|
|
4445
|
+
/**
|
|
4446
|
+
* Converts a CSV string into an object
|
|
4447
|
+
*
|
|
4448
|
+
* Note: This is wrapper around `papaparse.parse()` with better autohealing
|
|
4449
|
+
*
|
|
4450
|
+
* @private - for now until `@promptbook/csv` is released
|
|
4451
|
+
*/
|
|
4452
|
+
function csvParse(value /* <- TODO: string_csv */, settings, schema /* <- TODO: Make CSV Schemas */) {
|
|
4453
|
+
settings = { ...settings, ...MANDATORY_CSV_SETTINGS };
|
|
4454
|
+
// Note: Autoheal invalid '\n' characters
|
|
4455
|
+
if (settings.newline && !settings.newline.includes('\r') && value.includes('\r')) {
|
|
4456
|
+
console.warn('CSV string contains carriage return characters, but in the CSV settings the `newline` setting does not include them. Autohealing the CSV string.');
|
|
4457
|
+
value = value.replace(/\r\n/g, '\n').replace(/\r/g, '\n');
|
|
4458
|
+
}
|
|
4459
|
+
const csv = papaparse.parse(value, settings);
|
|
4460
|
+
return csv;
|
|
4461
|
+
}
|
|
4462
|
+
|
|
4299
4463
|
/**
|
|
4300
4464
|
* Definition for CSV spreadsheet
|
|
4301
4465
|
*
|
|
@@ -4306,7 +4470,7 @@
|
|
|
4306
4470
|
formatName: 'CSV',
|
|
4307
4471
|
aliases: ['SPREADSHEET', 'TABLE'],
|
|
4308
4472
|
isValid(value, settings, schema) {
|
|
4309
|
-
return
|
|
4473
|
+
return isValidCsvString(value);
|
|
4310
4474
|
},
|
|
4311
4475
|
canBeValid(partialValue, settings, schema) {
|
|
4312
4476
|
return true;
|
|
@@ -4318,8 +4482,7 @@
|
|
|
4318
4482
|
{
|
|
4319
4483
|
subvalueName: 'ROW',
|
|
4320
4484
|
async mapValues(value, outputParameterName, settings, mapCallback) {
|
|
4321
|
-
|
|
4322
|
-
const csv = papaparse.parse(value, { ...settings, ...MANDATORY_CSV_SETTINGS });
|
|
4485
|
+
const csv = csvParse(value, settings);
|
|
4323
4486
|
if (csv.errors.length !== 0) {
|
|
4324
4487
|
throw new CsvFormatError(spaceTrim__default["default"]((block) => `
|
|
4325
4488
|
CSV parsing error
|
|
@@ -4349,8 +4512,7 @@
|
|
|
4349
4512
|
{
|
|
4350
4513
|
subvalueName: 'CELL',
|
|
4351
4514
|
async mapValues(value, outputParameterName, settings, mapCallback) {
|
|
4352
|
-
|
|
4353
|
-
const csv = papaparse.parse(value, { ...settings, ...MANDATORY_CSV_SETTINGS });
|
|
4515
|
+
const csv = csvParse(value, settings);
|
|
4354
4516
|
if (csv.errors.length !== 0) {
|
|
4355
4517
|
throw new CsvFormatError(spaceTrim__default["default"]((block) => `
|
|
4356
4518
|
CSV parsing error
|
|
@@ -4460,6 +4622,30 @@
|
|
|
4460
4622
|
* TODO: [🏢] Allow to expect something inside each item of list and other formats
|
|
4461
4623
|
*/
|
|
4462
4624
|
|
|
4625
|
+
/**
|
|
4626
|
+
* Function to check if a string is valid XML
|
|
4627
|
+
*
|
|
4628
|
+
* @param value
|
|
4629
|
+
* @returns True if the string is a valid XML string, false otherwise
|
|
4630
|
+
*
|
|
4631
|
+
* @public exported from `@promptbook/utils`
|
|
4632
|
+
*/
|
|
4633
|
+
function isValidXmlString(value) {
|
|
4634
|
+
try {
|
|
4635
|
+
const parser = new DOMParser();
|
|
4636
|
+
const parsedDocument = parser.parseFromString(value, 'application/xml');
|
|
4637
|
+
const parserError = parsedDocument.getElementsByTagName('parsererror');
|
|
4638
|
+
if (parserError.length > 0) {
|
|
4639
|
+
return false;
|
|
4640
|
+
}
|
|
4641
|
+
return true;
|
|
4642
|
+
}
|
|
4643
|
+
catch (error) {
|
|
4644
|
+
assertsError(error);
|
|
4645
|
+
return false;
|
|
4646
|
+
}
|
|
4647
|
+
}
|
|
4648
|
+
|
|
4463
4649
|
/**
|
|
4464
4650
|
* Definition for XML format
|
|
4465
4651
|
*
|
|
@@ -4469,7 +4655,7 @@
|
|
|
4469
4655
|
formatName: 'XML',
|
|
4470
4656
|
mimeType: 'application/xml',
|
|
4471
4657
|
isValid(value, settings, schema) {
|
|
4472
|
-
return
|
|
4658
|
+
return isValidXmlString(value);
|
|
4473
4659
|
},
|
|
4474
4660
|
canBeValid(partialValue, settings, schema) {
|
|
4475
4661
|
return true;
|
|
@@ -5059,9 +5245,7 @@
|
|
|
5059
5245
|
break scripts;
|
|
5060
5246
|
}
|
|
5061
5247
|
catch (error) {
|
|
5062
|
-
|
|
5063
|
-
throw error;
|
|
5064
|
-
}
|
|
5248
|
+
assertsError(error);
|
|
5065
5249
|
if (error instanceof UnexpectedError) {
|
|
5066
5250
|
throw error;
|
|
5067
5251
|
}
|
|
@@ -5131,9 +5315,7 @@
|
|
|
5131
5315
|
break scripts;
|
|
5132
5316
|
}
|
|
5133
5317
|
catch (error) {
|
|
5134
|
-
|
|
5135
|
-
throw error;
|
|
5136
|
-
}
|
|
5318
|
+
assertsError(error);
|
|
5137
5319
|
if (error instanceof UnexpectedError) {
|
|
5138
5320
|
throw error;
|
|
5139
5321
|
}
|
|
@@ -5376,13 +5558,79 @@
|
|
|
5376
5558
|
/**
|
|
5377
5559
|
* @@@
|
|
5378
5560
|
*
|
|
5561
|
+
* Here is the place where RAG (retrieval-augmented generation) happens
|
|
5562
|
+
*
|
|
5379
5563
|
* @private internal utility of `createPipelineExecutor`
|
|
5380
5564
|
*/
|
|
5381
5565
|
async function getKnowledgeForTask(options) {
|
|
5382
|
-
const { preparedPipeline, task } = options;
|
|
5383
|
-
|
|
5566
|
+
const { tools, preparedPipeline, task } = options;
|
|
5567
|
+
const firstKnowlegePiece = preparedPipeline.knowledgePieces[0];
|
|
5568
|
+
const firstKnowlegeIndex = firstKnowlegePiece === null || firstKnowlegePiece === void 0 ? void 0 : firstKnowlegePiece.index[0];
|
|
5569
|
+
// <- TODO: Do not use just first knowledge piece and first index to determine embedding model, use also keyword search
|
|
5570
|
+
if (firstKnowlegePiece === undefined || firstKnowlegeIndex === undefined) {
|
|
5571
|
+
return 'No knowledge pieces found';
|
|
5572
|
+
}
|
|
5573
|
+
// TODO: [🚐] Make arrayable LLMs -> single LLM DRY
|
|
5574
|
+
const _llms = arrayableToArray(tools.llm);
|
|
5575
|
+
const llmTools = _llms.length === 1 ? _llms[0] : joinLlmExecutionTools(..._llms);
|
|
5576
|
+
const taskEmbeddingPrompt = {
|
|
5577
|
+
title: 'Knowledge Search',
|
|
5578
|
+
modelRequirements: {
|
|
5579
|
+
modelVariant: 'EMBEDDING',
|
|
5580
|
+
modelName: firstKnowlegeIndex.modelName,
|
|
5581
|
+
},
|
|
5582
|
+
content: task.content,
|
|
5583
|
+
parameters: {
|
|
5584
|
+
/* !!!!!!!! */
|
|
5585
|
+
},
|
|
5586
|
+
};
|
|
5587
|
+
const taskEmbeddingResult = await llmTools.callEmbeddingModel(taskEmbeddingPrompt);
|
|
5588
|
+
const knowledgePiecesWithRelevance = preparedPipeline.knowledgePieces.map((knowledgePiece) => {
|
|
5589
|
+
const { index } = knowledgePiece;
|
|
5590
|
+
const knowledgePieceIndex = index.find((i) => i.modelName === firstKnowlegeIndex.modelName);
|
|
5591
|
+
// <- TODO: Do not use just first knowledge piece and first index to determine embedding model
|
|
5592
|
+
if (knowledgePieceIndex === undefined) {
|
|
5593
|
+
return {
|
|
5594
|
+
content: knowledgePiece.content,
|
|
5595
|
+
relevance: 0,
|
|
5596
|
+
};
|
|
5597
|
+
}
|
|
5598
|
+
const relevance = computeCosineSimilarity(knowledgePieceIndex.position, taskEmbeddingResult.content);
|
|
5599
|
+
return {
|
|
5600
|
+
content: knowledgePiece.content,
|
|
5601
|
+
relevance,
|
|
5602
|
+
};
|
|
5603
|
+
});
|
|
5604
|
+
const knowledgePiecesSorted = knowledgePiecesWithRelevance.sort((a, b) => a.relevance - b.relevance);
|
|
5605
|
+
const knowledgePiecesLimited = knowledgePiecesSorted.slice(0, 5);
|
|
5606
|
+
console.log('!!! Embedding', {
|
|
5607
|
+
task,
|
|
5608
|
+
taskEmbeddingPrompt,
|
|
5609
|
+
taskEmbeddingResult,
|
|
5610
|
+
firstKnowlegePiece,
|
|
5611
|
+
firstKnowlegeIndex,
|
|
5612
|
+
knowledgePiecesWithRelevance,
|
|
5613
|
+
knowledgePiecesSorted,
|
|
5614
|
+
knowledgePiecesLimited,
|
|
5615
|
+
});
|
|
5616
|
+
return knowledgePiecesLimited.map(({ content }) => `- ${content}`).join('\n');
|
|
5384
5617
|
// <- TODO: [🧠] Some smart aggregation of knowledge pieces, single-line vs multi-line vs mixed
|
|
5385
5618
|
}
|
|
5619
|
+
// TODO: !!!!!! Annotate + to new file
|
|
5620
|
+
function computeCosineSimilarity(embeddingVector1, embeddingVector2) {
|
|
5621
|
+
if (embeddingVector1.length !== embeddingVector2.length) {
|
|
5622
|
+
throw new TypeError('Embedding vectors must have the same length');
|
|
5623
|
+
}
|
|
5624
|
+
const dotProduct = embeddingVector1.reduce((sum, value, index) => sum + value * embeddingVector2[index], 0);
|
|
5625
|
+
const magnitude1 = Math.sqrt(embeddingVector1.reduce((sum, value) => sum + value * value, 0));
|
|
5626
|
+
const magnitude2 = Math.sqrt(embeddingVector2.reduce((sum, value) => sum + value * value, 0));
|
|
5627
|
+
return 1 - dotProduct / (magnitude1 * magnitude2);
|
|
5628
|
+
}
|
|
5629
|
+
/**
|
|
5630
|
+
* TODO: !!!! Verify if this is working
|
|
5631
|
+
* TODO: [♨] Implement Better - use keyword search
|
|
5632
|
+
* TODO: [♨] Examples of values
|
|
5633
|
+
*/
|
|
5386
5634
|
|
|
5387
5635
|
/**
|
|
5388
5636
|
* @@@
|
|
@@ -5390,9 +5638,9 @@
|
|
|
5390
5638
|
* @private internal utility of `createPipelineExecutor`
|
|
5391
5639
|
*/
|
|
5392
5640
|
async function getReservedParametersForTask(options) {
|
|
5393
|
-
const { preparedPipeline, task, pipelineIdentification } = options;
|
|
5641
|
+
const { tools, preparedPipeline, task, pipelineIdentification } = options;
|
|
5394
5642
|
const context = await getContextForTask(); // <- [🏍]
|
|
5395
|
-
const knowledge = await getKnowledgeForTask({ preparedPipeline, task });
|
|
5643
|
+
const knowledge = await getKnowledgeForTask({ tools, preparedPipeline, task });
|
|
5396
5644
|
const examples = await getExamplesForTask();
|
|
5397
5645
|
const currentDate = new Date().toISOString(); // <- TODO: [🧠][💩] Better
|
|
5398
5646
|
const modelName = RESERVED_PARAMETER_MISSING_VALUE;
|
|
@@ -5454,6 +5702,7 @@
|
|
|
5454
5702
|
}
|
|
5455
5703
|
const definedParameters = Object.freeze({
|
|
5456
5704
|
...(await getReservedParametersForTask({
|
|
5705
|
+
tools,
|
|
5457
5706
|
preparedPipeline,
|
|
5458
5707
|
task: currentTask,
|
|
5459
5708
|
pipelineIdentification,
|
|
@@ -5754,9 +6003,7 @@
|
|
|
5754
6003
|
await Promise.all(resolving);
|
|
5755
6004
|
}
|
|
5756
6005
|
catch (error /* <- Note: [3] */) {
|
|
5757
|
-
|
|
5758
|
-
throw error;
|
|
5759
|
-
}
|
|
6006
|
+
assertsError(error);
|
|
5760
6007
|
// Note: No need to rethrow UnexpectedError
|
|
5761
6008
|
// if (error instanceof UnexpectedError) {
|
|
5762
6009
|
// Note: Count usage, [🧠] Maybe put to separate function executionReportJsonToUsage + DRY [🤹♂️]
|
|
@@ -6658,9 +6905,7 @@
|
|
|
6658
6905
|
}
|
|
6659
6906
|
}
|
|
6660
6907
|
catch (error) {
|
|
6661
|
-
|
|
6662
|
-
throw error;
|
|
6663
|
-
}
|
|
6908
|
+
assertsError(error);
|
|
6664
6909
|
if (error instanceof ReferenceError) {
|
|
6665
6910
|
const undefinedName = error.message.split(' ')[0];
|
|
6666
6911
|
/*
|
|
@@ -6740,6 +6985,604 @@
|
|
|
6740
6985
|
* Note: [🟢] Code in this file should never be never released in packages that could be imported into browser environment
|
|
6741
6986
|
*/
|
|
6742
6987
|
|
|
6988
|
+
// TODO: !!!! List running services from REMOTE_SERVER_URLS
|
|
6989
|
+
// TODO: !!!! Import directly from YML
|
|
6990
|
+
/**
|
|
6991
|
+
* @private !!!! Decide how to expose this
|
|
6992
|
+
*/
|
|
6993
|
+
const openapiJson = {
|
|
6994
|
+
openapi: '3.0.0',
|
|
6995
|
+
info: {
|
|
6996
|
+
title: 'Promptbook Remote Server API (!!!! From YML)',
|
|
6997
|
+
version: '1.0.0',
|
|
6998
|
+
description: 'API documentation for the Promptbook Remote Server',
|
|
6999
|
+
},
|
|
7000
|
+
paths: {
|
|
7001
|
+
'/': {
|
|
7002
|
+
get: {
|
|
7003
|
+
summary: 'Get server details',
|
|
7004
|
+
description: 'Returns details about the Promptbook server.',
|
|
7005
|
+
responses: {
|
|
7006
|
+
'200': {
|
|
7007
|
+
description: 'Server details in markdown format.',
|
|
7008
|
+
content: {
|
|
7009
|
+
'text/markdown': {
|
|
7010
|
+
schema: {
|
|
7011
|
+
type: 'string',
|
|
7012
|
+
},
|
|
7013
|
+
},
|
|
7014
|
+
},
|
|
7015
|
+
},
|
|
7016
|
+
},
|
|
7017
|
+
},
|
|
7018
|
+
},
|
|
7019
|
+
'/login': {
|
|
7020
|
+
post: {
|
|
7021
|
+
summary: 'Login to the server',
|
|
7022
|
+
description: 'Login to the server and get identification.',
|
|
7023
|
+
requestBody: {
|
|
7024
|
+
required: true,
|
|
7025
|
+
content: {
|
|
7026
|
+
'application/json': {
|
|
7027
|
+
schema: {
|
|
7028
|
+
type: 'object',
|
|
7029
|
+
properties: {
|
|
7030
|
+
username: {
|
|
7031
|
+
type: 'string',
|
|
7032
|
+
},
|
|
7033
|
+
password: {
|
|
7034
|
+
type: 'string',
|
|
7035
|
+
},
|
|
7036
|
+
appId: {
|
|
7037
|
+
type: 'string',
|
|
7038
|
+
},
|
|
7039
|
+
},
|
|
7040
|
+
},
|
|
7041
|
+
},
|
|
7042
|
+
},
|
|
7043
|
+
},
|
|
7044
|
+
responses: {
|
|
7045
|
+
'201': {
|
|
7046
|
+
description: 'Successful login',
|
|
7047
|
+
content: {
|
|
7048
|
+
'application/json': {
|
|
7049
|
+
schema: {
|
|
7050
|
+
type: 'object',
|
|
7051
|
+
properties: {
|
|
7052
|
+
isSuccess: {
|
|
7053
|
+
type: 'boolean',
|
|
7054
|
+
},
|
|
7055
|
+
message: {
|
|
7056
|
+
type: 'string',
|
|
7057
|
+
},
|
|
7058
|
+
error: {
|
|
7059
|
+
type: 'object',
|
|
7060
|
+
},
|
|
7061
|
+
identification: {
|
|
7062
|
+
type: 'object',
|
|
7063
|
+
},
|
|
7064
|
+
},
|
|
7065
|
+
},
|
|
7066
|
+
},
|
|
7067
|
+
},
|
|
7068
|
+
},
|
|
7069
|
+
'400': {
|
|
7070
|
+
description: 'Bad request or login failed',
|
|
7071
|
+
content: {
|
|
7072
|
+
'application/json': {
|
|
7073
|
+
schema: {
|
|
7074
|
+
type: 'object',
|
|
7075
|
+
properties: {
|
|
7076
|
+
error: {
|
|
7077
|
+
type: 'object',
|
|
7078
|
+
},
|
|
7079
|
+
},
|
|
7080
|
+
},
|
|
7081
|
+
},
|
|
7082
|
+
},
|
|
7083
|
+
},
|
|
7084
|
+
'401': {
|
|
7085
|
+
description: 'Authentication error',
|
|
7086
|
+
content: {
|
|
7087
|
+
'application/json': {
|
|
7088
|
+
schema: {
|
|
7089
|
+
type: 'object',
|
|
7090
|
+
properties: {
|
|
7091
|
+
isSuccess: {
|
|
7092
|
+
type: 'boolean',
|
|
7093
|
+
enum: [false],
|
|
7094
|
+
},
|
|
7095
|
+
message: {
|
|
7096
|
+
type: 'string',
|
|
7097
|
+
},
|
|
7098
|
+
error: {
|
|
7099
|
+
type: 'object',
|
|
7100
|
+
},
|
|
7101
|
+
},
|
|
7102
|
+
},
|
|
7103
|
+
},
|
|
7104
|
+
},
|
|
7105
|
+
},
|
|
7106
|
+
},
|
|
7107
|
+
},
|
|
7108
|
+
},
|
|
7109
|
+
'/books': {
|
|
7110
|
+
get: {
|
|
7111
|
+
summary: 'List all books',
|
|
7112
|
+
description: 'Returns a list of all available books in the collection.',
|
|
7113
|
+
responses: {
|
|
7114
|
+
'200': {
|
|
7115
|
+
description: 'A list of books.',
|
|
7116
|
+
content: {
|
|
7117
|
+
'application/json': {
|
|
7118
|
+
schema: {
|
|
7119
|
+
type: 'array',
|
|
7120
|
+
items: {
|
|
7121
|
+
type: 'string',
|
|
7122
|
+
},
|
|
7123
|
+
},
|
|
7124
|
+
},
|
|
7125
|
+
},
|
|
7126
|
+
},
|
|
7127
|
+
'500': {
|
|
7128
|
+
description: 'No collection available',
|
|
7129
|
+
content: {
|
|
7130
|
+
'text/plain': {
|
|
7131
|
+
schema: {
|
|
7132
|
+
type: 'string',
|
|
7133
|
+
},
|
|
7134
|
+
},
|
|
7135
|
+
},
|
|
7136
|
+
},
|
|
7137
|
+
},
|
|
7138
|
+
},
|
|
7139
|
+
},
|
|
7140
|
+
'/books/{bookId}': {
|
|
7141
|
+
get: {
|
|
7142
|
+
summary: 'Get book content',
|
|
7143
|
+
description: 'Returns the content of a specific book.',
|
|
7144
|
+
parameters: [
|
|
7145
|
+
{
|
|
7146
|
+
in: 'path',
|
|
7147
|
+
name: 'bookId',
|
|
7148
|
+
required: true,
|
|
7149
|
+
schema: {
|
|
7150
|
+
type: 'string',
|
|
7151
|
+
},
|
|
7152
|
+
description: 'The ID of the book to retrieve.',
|
|
7153
|
+
},
|
|
7154
|
+
],
|
|
7155
|
+
responses: {
|
|
7156
|
+
'200': {
|
|
7157
|
+
description: 'The content of the book.',
|
|
7158
|
+
content: {
|
|
7159
|
+
'text/markdown': {
|
|
7160
|
+
schema: {
|
|
7161
|
+
type: 'string',
|
|
7162
|
+
},
|
|
7163
|
+
},
|
|
7164
|
+
},
|
|
7165
|
+
},
|
|
7166
|
+
'404': {
|
|
7167
|
+
description: 'Book not found.',
|
|
7168
|
+
content: {
|
|
7169
|
+
'application/json': {
|
|
7170
|
+
schema: {
|
|
7171
|
+
type: 'object',
|
|
7172
|
+
properties: {
|
|
7173
|
+
error: {
|
|
7174
|
+
type: 'object',
|
|
7175
|
+
},
|
|
7176
|
+
},
|
|
7177
|
+
},
|
|
7178
|
+
},
|
|
7179
|
+
},
|
|
7180
|
+
},
|
|
7181
|
+
'500': {
|
|
7182
|
+
description: 'No collection available',
|
|
7183
|
+
content: {
|
|
7184
|
+
'text/plain': {
|
|
7185
|
+
schema: {
|
|
7186
|
+
type: 'string',
|
|
7187
|
+
},
|
|
7188
|
+
},
|
|
7189
|
+
},
|
|
7190
|
+
},
|
|
7191
|
+
},
|
|
7192
|
+
},
|
|
7193
|
+
},
|
|
7194
|
+
'/executions': {
|
|
7195
|
+
get: {
|
|
7196
|
+
summary: 'List all executions',
|
|
7197
|
+
description: 'Returns a list of all running execution tasks.',
|
|
7198
|
+
responses: {
|
|
7199
|
+
'200': {
|
|
7200
|
+
description: 'A list of execution tasks.',
|
|
7201
|
+
content: {
|
|
7202
|
+
'application/json': {
|
|
7203
|
+
schema: {
|
|
7204
|
+
type: 'array',
|
|
7205
|
+
items: {
|
|
7206
|
+
type: 'object',
|
|
7207
|
+
properties: {
|
|
7208
|
+
nonce: {
|
|
7209
|
+
type: 'string',
|
|
7210
|
+
},
|
|
7211
|
+
taskId: {
|
|
7212
|
+
type: 'string',
|
|
7213
|
+
},
|
|
7214
|
+
taskType: {
|
|
7215
|
+
type: 'string',
|
|
7216
|
+
},
|
|
7217
|
+
status: {
|
|
7218
|
+
type: 'string',
|
|
7219
|
+
},
|
|
7220
|
+
createdAt: {
|
|
7221
|
+
type: 'string',
|
|
7222
|
+
format: 'date-time',
|
|
7223
|
+
},
|
|
7224
|
+
updatedAt: {
|
|
7225
|
+
type: 'string',
|
|
7226
|
+
format: 'date-time',
|
|
7227
|
+
},
|
|
7228
|
+
},
|
|
7229
|
+
},
|
|
7230
|
+
},
|
|
7231
|
+
},
|
|
7232
|
+
},
|
|
7233
|
+
},
|
|
7234
|
+
},
|
|
7235
|
+
},
|
|
7236
|
+
},
|
|
7237
|
+
'/executions/last': {
|
|
7238
|
+
get: {
|
|
7239
|
+
summary: 'Get the last execution',
|
|
7240
|
+
description: 'Returns details of the last execution task.',
|
|
7241
|
+
responses: {
|
|
7242
|
+
'200': {
|
|
7243
|
+
description: 'The last execution task with full details.',
|
|
7244
|
+
content: {
|
|
7245
|
+
'application/json': {
|
|
7246
|
+
schema: {
|
|
7247
|
+
type: 'object',
|
|
7248
|
+
properties: {
|
|
7249
|
+
nonce: {
|
|
7250
|
+
type: 'string',
|
|
7251
|
+
},
|
|
7252
|
+
taskId: {
|
|
7253
|
+
type: 'string',
|
|
7254
|
+
},
|
|
7255
|
+
taskType: {
|
|
7256
|
+
type: 'string',
|
|
7257
|
+
},
|
|
7258
|
+
status: {
|
|
7259
|
+
type: 'string',
|
|
7260
|
+
},
|
|
7261
|
+
errors: {
|
|
7262
|
+
type: 'array',
|
|
7263
|
+
items: {
|
|
7264
|
+
type: 'object',
|
|
7265
|
+
},
|
|
7266
|
+
},
|
|
7267
|
+
warnings: {
|
|
7268
|
+
type: 'array',
|
|
7269
|
+
items: {
|
|
7270
|
+
type: 'object',
|
|
7271
|
+
},
|
|
7272
|
+
},
|
|
7273
|
+
createdAt: {
|
|
7274
|
+
type: 'string',
|
|
7275
|
+
format: 'date-time',
|
|
7276
|
+
},
|
|
7277
|
+
updatedAt: {
|
|
7278
|
+
type: 'string',
|
|
7279
|
+
format: 'date-time',
|
|
7280
|
+
},
|
|
7281
|
+
currentValue: {
|
|
7282
|
+
type: 'object',
|
|
7283
|
+
},
|
|
7284
|
+
},
|
|
7285
|
+
},
|
|
7286
|
+
},
|
|
7287
|
+
},
|
|
7288
|
+
},
|
|
7289
|
+
'404': {
|
|
7290
|
+
description: 'No execution tasks found.',
|
|
7291
|
+
content: {
|
|
7292
|
+
'text/plain': {
|
|
7293
|
+
schema: {
|
|
7294
|
+
type: 'string',
|
|
7295
|
+
},
|
|
7296
|
+
},
|
|
7297
|
+
},
|
|
7298
|
+
},
|
|
7299
|
+
},
|
|
7300
|
+
},
|
|
7301
|
+
},
|
|
7302
|
+
'/executions/{taskId}': {
|
|
7303
|
+
get: {
|
|
7304
|
+
summary: 'Get specific execution',
|
|
7305
|
+
description: 'Returns details of a specific execution task.',
|
|
7306
|
+
parameters: [
|
|
7307
|
+
{
|
|
7308
|
+
in: 'path',
|
|
7309
|
+
name: 'taskId',
|
|
7310
|
+
required: true,
|
|
7311
|
+
schema: {
|
|
7312
|
+
type: 'string',
|
|
7313
|
+
},
|
|
7314
|
+
description: 'The ID of the execution task to retrieve.',
|
|
7315
|
+
},
|
|
7316
|
+
],
|
|
7317
|
+
responses: {
|
|
7318
|
+
'200': {
|
|
7319
|
+
description: 'The execution task with full details.',
|
|
7320
|
+
content: {
|
|
7321
|
+
'application/json': {
|
|
7322
|
+
schema: {
|
|
7323
|
+
type: 'object',
|
|
7324
|
+
properties: {
|
|
7325
|
+
nonce: {
|
|
7326
|
+
type: 'string',
|
|
7327
|
+
},
|
|
7328
|
+
taskId: {
|
|
7329
|
+
type: 'string',
|
|
7330
|
+
},
|
|
7331
|
+
taskType: {
|
|
7332
|
+
type: 'string',
|
|
7333
|
+
},
|
|
7334
|
+
status: {
|
|
7335
|
+
type: 'string',
|
|
7336
|
+
},
|
|
7337
|
+
errors: {
|
|
7338
|
+
type: 'array',
|
|
7339
|
+
items: {
|
|
7340
|
+
type: 'object',
|
|
7341
|
+
},
|
|
7342
|
+
},
|
|
7343
|
+
warnings: {
|
|
7344
|
+
type: 'array',
|
|
7345
|
+
items: {
|
|
7346
|
+
type: 'object',
|
|
7347
|
+
},
|
|
7348
|
+
},
|
|
7349
|
+
createdAt: {
|
|
7350
|
+
type: 'string',
|
|
7351
|
+
format: 'date-time',
|
|
7352
|
+
},
|
|
7353
|
+
updatedAt: {
|
|
7354
|
+
type: 'string',
|
|
7355
|
+
format: 'date-time',
|
|
7356
|
+
},
|
|
7357
|
+
currentValue: {
|
|
7358
|
+
type: 'object',
|
|
7359
|
+
},
|
|
7360
|
+
},
|
|
7361
|
+
},
|
|
7362
|
+
},
|
|
7363
|
+
},
|
|
7364
|
+
},
|
|
7365
|
+
'404': {
|
|
7366
|
+
description: 'Execution task not found.',
|
|
7367
|
+
content: {
|
|
7368
|
+
'text/plain': {
|
|
7369
|
+
schema: {
|
|
7370
|
+
type: 'string',
|
|
7371
|
+
},
|
|
7372
|
+
},
|
|
7373
|
+
},
|
|
7374
|
+
},
|
|
7375
|
+
},
|
|
7376
|
+
},
|
|
7377
|
+
},
|
|
7378
|
+
'/executions/new': {
|
|
7379
|
+
post: {
|
|
7380
|
+
summary: 'Start a new execution',
|
|
7381
|
+
description: 'Starts a new execution task for a given pipeline.',
|
|
7382
|
+
requestBody: {
|
|
7383
|
+
required: true,
|
|
7384
|
+
content: {
|
|
7385
|
+
'application/json': {
|
|
7386
|
+
schema: {
|
|
7387
|
+
type: 'object',
|
|
7388
|
+
properties: {
|
|
7389
|
+
pipelineUrl: {
|
|
7390
|
+
type: 'string',
|
|
7391
|
+
description: 'URL of the pipeline to execute',
|
|
7392
|
+
},
|
|
7393
|
+
book: {
|
|
7394
|
+
type: 'string',
|
|
7395
|
+
description: 'Alternative field for pipelineUrl',
|
|
7396
|
+
},
|
|
7397
|
+
inputParameters: {
|
|
7398
|
+
type: 'object',
|
|
7399
|
+
description: 'Parameters for pipeline execution',
|
|
7400
|
+
},
|
|
7401
|
+
identification: {
|
|
7402
|
+
type: 'object',
|
|
7403
|
+
description: 'User identification data',
|
|
7404
|
+
},
|
|
7405
|
+
},
|
|
7406
|
+
},
|
|
7407
|
+
},
|
|
7408
|
+
},
|
|
7409
|
+
},
|
|
7410
|
+
responses: {
|
|
7411
|
+
'200': {
|
|
7412
|
+
description: 'The newly created execution task.',
|
|
7413
|
+
content: {
|
|
7414
|
+
'application/json': {
|
|
7415
|
+
schema: {
|
|
7416
|
+
type: 'object',
|
|
7417
|
+
},
|
|
7418
|
+
},
|
|
7419
|
+
},
|
|
7420
|
+
},
|
|
7421
|
+
'400': {
|
|
7422
|
+
description: 'Invalid input.',
|
|
7423
|
+
content: {
|
|
7424
|
+
'application/json': {
|
|
7425
|
+
schema: {
|
|
7426
|
+
type: 'object',
|
|
7427
|
+
properties: {
|
|
7428
|
+
error: {
|
|
7429
|
+
type: 'object',
|
|
7430
|
+
},
|
|
7431
|
+
},
|
|
7432
|
+
},
|
|
7433
|
+
},
|
|
7434
|
+
},
|
|
7435
|
+
},
|
|
7436
|
+
'404': {
|
|
7437
|
+
description: 'Pipeline not found.',
|
|
7438
|
+
content: {
|
|
7439
|
+
'text/plain': {
|
|
7440
|
+
schema: {
|
|
7441
|
+
type: 'string',
|
|
7442
|
+
},
|
|
7443
|
+
},
|
|
7444
|
+
},
|
|
7445
|
+
},
|
|
7446
|
+
},
|
|
7447
|
+
},
|
|
7448
|
+
},
|
|
7449
|
+
'/api-docs': {
|
|
7450
|
+
get: {
|
|
7451
|
+
summary: 'API documentation UI',
|
|
7452
|
+
description: 'Swagger UI for API documentation',
|
|
7453
|
+
responses: {
|
|
7454
|
+
'200': {
|
|
7455
|
+
description: 'HTML Swagger UI',
|
|
7456
|
+
},
|
|
7457
|
+
},
|
|
7458
|
+
},
|
|
7459
|
+
},
|
|
7460
|
+
'/swagger': {
|
|
7461
|
+
get: {
|
|
7462
|
+
summary: 'API documentation UI (alternative path)',
|
|
7463
|
+
description: 'Swagger UI for API documentation',
|
|
7464
|
+
responses: {
|
|
7465
|
+
'200': {
|
|
7466
|
+
description: 'HTML Swagger UI',
|
|
7467
|
+
},
|
|
7468
|
+
},
|
|
7469
|
+
},
|
|
7470
|
+
},
|
|
7471
|
+
'/openapi': {
|
|
7472
|
+
get: {
|
|
7473
|
+
summary: 'OpenAPI specification',
|
|
7474
|
+
description: 'Returns the OpenAPI JSON specification',
|
|
7475
|
+
responses: {
|
|
7476
|
+
'200': {
|
|
7477
|
+
description: 'OpenAPI specification',
|
|
7478
|
+
content: {
|
|
7479
|
+
'application/json': {
|
|
7480
|
+
schema: {
|
|
7481
|
+
type: 'object',
|
|
7482
|
+
},
|
|
7483
|
+
},
|
|
7484
|
+
},
|
|
7485
|
+
},
|
|
7486
|
+
},
|
|
7487
|
+
},
|
|
7488
|
+
},
|
|
7489
|
+
},
|
|
7490
|
+
components: {
|
|
7491
|
+
schemas: {
|
|
7492
|
+
Error: {
|
|
7493
|
+
type: 'object',
|
|
7494
|
+
properties: {
|
|
7495
|
+
error: {
|
|
7496
|
+
type: 'object',
|
|
7497
|
+
},
|
|
7498
|
+
},
|
|
7499
|
+
},
|
|
7500
|
+
ExecutionTaskSummary: {
|
|
7501
|
+
type: 'object',
|
|
7502
|
+
properties: {
|
|
7503
|
+
nonce: {
|
|
7504
|
+
type: 'string',
|
|
7505
|
+
},
|
|
7506
|
+
taskId: {
|
|
7507
|
+
type: 'string',
|
|
7508
|
+
},
|
|
7509
|
+
taskType: {
|
|
7510
|
+
type: 'string',
|
|
7511
|
+
},
|
|
7512
|
+
status: {
|
|
7513
|
+
type: 'string',
|
|
7514
|
+
},
|
|
7515
|
+
createdAt: {
|
|
7516
|
+
type: 'string',
|
|
7517
|
+
format: 'date-time',
|
|
7518
|
+
},
|
|
7519
|
+
updatedAt: {
|
|
7520
|
+
type: 'string',
|
|
7521
|
+
format: 'date-time',
|
|
7522
|
+
},
|
|
7523
|
+
},
|
|
7524
|
+
},
|
|
7525
|
+
ExecutionTaskFull: {
|
|
7526
|
+
type: 'object',
|
|
7527
|
+
properties: {
|
|
7528
|
+
nonce: {
|
|
7529
|
+
type: 'string',
|
|
7530
|
+
},
|
|
7531
|
+
taskId: {
|
|
7532
|
+
type: 'string',
|
|
7533
|
+
},
|
|
7534
|
+
taskType: {
|
|
7535
|
+
type: 'string',
|
|
7536
|
+
},
|
|
7537
|
+
status: {
|
|
7538
|
+
type: 'string',
|
|
7539
|
+
},
|
|
7540
|
+
errors: {
|
|
7541
|
+
type: 'array',
|
|
7542
|
+
items: {
|
|
7543
|
+
type: 'object',
|
|
7544
|
+
},
|
|
7545
|
+
},
|
|
7546
|
+
warnings: {
|
|
7547
|
+
type: 'array',
|
|
7548
|
+
items: {
|
|
7549
|
+
type: 'object',
|
|
7550
|
+
},
|
|
7551
|
+
},
|
|
7552
|
+
createdAt: {
|
|
7553
|
+
type: 'string',
|
|
7554
|
+
format: 'date-time',
|
|
7555
|
+
},
|
|
7556
|
+
updatedAt: {
|
|
7557
|
+
type: 'string',
|
|
7558
|
+
format: 'date-time',
|
|
7559
|
+
},
|
|
7560
|
+
currentValue: {
|
|
7561
|
+
type: 'object',
|
|
7562
|
+
},
|
|
7563
|
+
},
|
|
7564
|
+
},
|
|
7565
|
+
},
|
|
7566
|
+
},
|
|
7567
|
+
tags: [
|
|
7568
|
+
{
|
|
7569
|
+
name: 'Books',
|
|
7570
|
+
description: 'Operations related to books and pipelines',
|
|
7571
|
+
},
|
|
7572
|
+
{
|
|
7573
|
+
name: 'Executions',
|
|
7574
|
+
description: 'Operations related to execution tasks',
|
|
7575
|
+
},
|
|
7576
|
+
{
|
|
7577
|
+
name: 'Authentication',
|
|
7578
|
+
description: 'Authentication operations',
|
|
7579
|
+
},
|
|
7580
|
+
],
|
|
7581
|
+
};
|
|
7582
|
+
/**
|
|
7583
|
+
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
7584
|
+
*/
|
|
7585
|
+
|
|
6743
7586
|
/**
|
|
6744
7587
|
* Remote server is a proxy server that uses its execution tools internally and exposes the executor interface externally.
|
|
6745
7588
|
*
|
|
@@ -6750,7 +7593,7 @@
|
|
|
6750
7593
|
* @public exported from `@promptbook/remote-server`
|
|
6751
7594
|
*/
|
|
6752
7595
|
function startRemoteServer(options) {
|
|
6753
|
-
const { port, collection, createLlmExecutionTools, isAnonymousModeAllowed, isApplicationModeAllowed, isVerbose = DEFAULT_IS_VERBOSE, login, } = {
|
|
7596
|
+
const { port, collection, createLlmExecutionTools, createExecutionTools, isAnonymousModeAllowed, isApplicationModeAllowed, isVerbose = DEFAULT_IS_VERBOSE, login, } = {
|
|
6754
7597
|
isAnonymousModeAllowed: false,
|
|
6755
7598
|
isApplicationModeAllowed: false,
|
|
6756
7599
|
collection: null,
|
|
@@ -6758,22 +7601,6 @@
|
|
|
6758
7601
|
login: null,
|
|
6759
7602
|
...options,
|
|
6760
7603
|
};
|
|
6761
|
-
// <- TODO: [🦪] Some helper type to be able to use discriminant union types with destructuring
|
|
6762
|
-
let { rootPath = '/' } = options;
|
|
6763
|
-
if (!rootPath.startsWith('/')) {
|
|
6764
|
-
rootPath = `/${rootPath}`;
|
|
6765
|
-
} /* not else */
|
|
6766
|
-
if (rootPath.endsWith('/')) {
|
|
6767
|
-
rootPath = rootPath.slice(0, -1);
|
|
6768
|
-
} /* not else */
|
|
6769
|
-
if (rootPath === '/') {
|
|
6770
|
-
rootPath = '';
|
|
6771
|
-
}
|
|
6772
|
-
const socketioPath = '/' +
|
|
6773
|
-
`${rootPath}/socket.io`
|
|
6774
|
-
.split('/')
|
|
6775
|
-
.filter((part) => part !== '')
|
|
6776
|
-
.join('/');
|
|
6777
7604
|
const startupDate = new Date();
|
|
6778
7605
|
async function getExecutionToolsFromIdentification(identification) {
|
|
6779
7606
|
if (identification === null || identification === undefined) {
|
|
@@ -6796,23 +7623,25 @@
|
|
|
6796
7623
|
}
|
|
6797
7624
|
else if (isAnonymous === false && createLlmExecutionTools !== null) {
|
|
6798
7625
|
// Note: Application mode
|
|
6799
|
-
|
|
6800
|
-
llm = await createLlmExecutionTools({
|
|
6801
|
-
appId,
|
|
6802
|
-
userId,
|
|
6803
|
-
customOptions,
|
|
6804
|
-
});
|
|
7626
|
+
llm = await createLlmExecutionTools(identification);
|
|
6805
7627
|
}
|
|
6806
7628
|
else {
|
|
6807
7629
|
throw new PipelineExecutionError(`You must provide either llmToolsConfiguration or non-anonymous mode must be propperly configured`);
|
|
6808
7630
|
}
|
|
6809
|
-
const
|
|
6810
|
-
const
|
|
7631
|
+
const customExecutionTools = createExecutionTools ? await createExecutionTools(identification) : {};
|
|
7632
|
+
const fs = customExecutionTools.fs || $provideFilesystemForNode();
|
|
7633
|
+
const executables = customExecutionTools.executables || (await $provideExecutablesForNode());
|
|
7634
|
+
const scrapers = customExecutionTools.scrapers || (await $provideScrapersForNode({ fs, llm, executables }));
|
|
7635
|
+
const script = customExecutionTools.script || (await $provideScriptingForNode({}));
|
|
7636
|
+
const fetch = customExecutionTools.fetch || promptbookFetch;
|
|
7637
|
+
const userInterface = customExecutionTools.userInterface || undefined;
|
|
6811
7638
|
const tools = {
|
|
6812
7639
|
llm,
|
|
6813
7640
|
fs,
|
|
6814
|
-
scrapers
|
|
6815
|
-
script
|
|
7641
|
+
scrapers,
|
|
7642
|
+
script,
|
|
7643
|
+
fetch,
|
|
7644
|
+
userInterface,
|
|
6816
7645
|
};
|
|
6817
7646
|
return tools;
|
|
6818
7647
|
}
|
|
@@ -6822,39 +7651,27 @@
|
|
|
6822
7651
|
response.setHeader('X-Powered-By', 'Promptbook engine');
|
|
6823
7652
|
next();
|
|
6824
7653
|
});
|
|
6825
|
-
|
|
6826
|
-
|
|
6827
|
-
|
|
6828
|
-
|
|
6829
|
-
|
|
6830
|
-
version: '1.0.0',
|
|
6831
|
-
description: 'API documentation for the Promptbook Remote Server',
|
|
6832
|
-
},
|
|
6833
|
-
servers: [
|
|
6834
|
-
{
|
|
6835
|
-
url: `http://localhost:${port}${rootPath}`,
|
|
6836
|
-
// <- TODO: !!!!! Probbably: Pass `remoteServerUrl` instead of `port` and `rootPath`
|
|
6837
|
-
},
|
|
6838
|
-
],
|
|
7654
|
+
// TODO: !!!! Expose openapiJson to consumer and also allow to add new routes
|
|
7655
|
+
app.use(OpenApiValidator__namespace.middleware({
|
|
7656
|
+
apiSpec: openapiJson,
|
|
7657
|
+
ignorePaths(path) {
|
|
7658
|
+
return path.startsWith('/api-docs') || path.startsWith('/swagger') || path.startsWith('/openapi');
|
|
6839
7659
|
},
|
|
6840
|
-
|
|
6841
|
-
|
|
6842
|
-
|
|
6843
|
-
app.use([`/api-docs`,
|
|
7660
|
+
validateRequests: true,
|
|
7661
|
+
validateResponses: true,
|
|
7662
|
+
}));
|
|
7663
|
+
app.use([`/api-docs`, `/swagger`], swaggerUi__default["default"].serve, swaggerUi__default["default"].setup(openapiJson, {
|
|
7664
|
+
// customCss: '.swagger-ui .topbar { display: none }',
|
|
7665
|
+
// customSiteTitle: 'BRJ API',
|
|
7666
|
+
// customfavIcon: 'https://brj.app/favicon.ico',
|
|
7667
|
+
}));
|
|
7668
|
+
app.get(`/openapi`, (request, response) => {
|
|
7669
|
+
response.json(openapiJson);
|
|
7670
|
+
});
|
|
6844
7671
|
const runningExecutionTasks = [];
|
|
6845
7672
|
// <- TODO: [🤬] Identify the users
|
|
6846
7673
|
// TODO: [🧠] Do here some garbage collection of finished tasks
|
|
6847
|
-
|
|
6848
|
-
* @swagger
|
|
6849
|
-
* /:
|
|
6850
|
-
* get:
|
|
6851
|
-
* summary: Get server details
|
|
6852
|
-
* description: Returns details about the Promptbook server.
|
|
6853
|
-
* responses:
|
|
6854
|
-
* 200:
|
|
6855
|
-
* description: Server details in markdown format.
|
|
6856
|
-
*/
|
|
6857
|
-
app.get(['/', rootPath], async (request, response) => {
|
|
7674
|
+
app.get('/', async (request, response) => {
|
|
6858
7675
|
var _a;
|
|
6859
7676
|
if ((_a = request.url) === null || _a === void 0 ? void 0 : _a.includes('socket.io')) {
|
|
6860
7677
|
return;
|
|
@@ -6873,8 +7690,6 @@
|
|
|
6873
7690
|
## Details
|
|
6874
7691
|
|
|
6875
7692
|
**Server port:** ${port}
|
|
6876
|
-
**Server root path:** ${rootPath}
|
|
6877
|
-
**Socket.io path:** ${socketioPath}
|
|
6878
7693
|
**Startup date:** ${startupDate.toISOString()}
|
|
6879
7694
|
**Anonymouse mode:** ${isAnonymousModeAllowed ? 'enabled' : 'disabled'}
|
|
6880
7695
|
**Application mode:** ${isApplicationModeAllowed ? 'enabled' : 'disabled'}
|
|
@@ -6913,38 +7728,7 @@
|
|
|
6913
7728
|
https://github.com/webgptorg/promptbook
|
|
6914
7729
|
`));
|
|
6915
7730
|
});
|
|
6916
|
-
|
|
6917
|
-
* @swagger
|
|
6918
|
-
*
|
|
6919
|
-
* /login:
|
|
6920
|
-
* post:
|
|
6921
|
-
* summary: Login to the server
|
|
6922
|
-
* description: Login to the server and get identification.
|
|
6923
|
-
* requestBody:
|
|
6924
|
-
* required: true
|
|
6925
|
-
* content:
|
|
6926
|
-
* application/json:
|
|
6927
|
-
* schema:
|
|
6928
|
-
* type: object
|
|
6929
|
-
* properties:
|
|
6930
|
-
* username:
|
|
6931
|
-
* type: string
|
|
6932
|
-
* password:
|
|
6933
|
-
* type: string
|
|
6934
|
-
* appId:
|
|
6935
|
-
* type: string
|
|
6936
|
-
* responses:
|
|
6937
|
-
* 200:
|
|
6938
|
-
* description: Successful login
|
|
6939
|
-
* content:
|
|
6940
|
-
* application/json:
|
|
6941
|
-
* schema:
|
|
6942
|
-
* type: object
|
|
6943
|
-
* properties:
|
|
6944
|
-
* identification:
|
|
6945
|
-
* type: object
|
|
6946
|
-
*/
|
|
6947
|
-
app.post([`/login`, `${rootPath}/login`], async (request, response) => {
|
|
7731
|
+
app.post(`/login`, async (request, response) => {
|
|
6948
7732
|
if (!isApplicationModeAllowed || login === null) {
|
|
6949
7733
|
response.status(400).send('Application mode is not allowed');
|
|
6950
7734
|
return;
|
|
@@ -6969,9 +7753,7 @@
|
|
|
6969
7753
|
return;
|
|
6970
7754
|
}
|
|
6971
7755
|
catch (error) {
|
|
6972
|
-
|
|
6973
|
-
throw error;
|
|
6974
|
-
}
|
|
7756
|
+
assertsError(error);
|
|
6975
7757
|
if (error instanceof AuthenticationError) {
|
|
6976
7758
|
response.status(401).send({
|
|
6977
7759
|
isSuccess: false,
|
|
@@ -6986,23 +7768,7 @@
|
|
|
6986
7768
|
response.status(400).send({ error: serializeError(error) });
|
|
6987
7769
|
}
|
|
6988
7770
|
});
|
|
6989
|
-
|
|
6990
|
-
* @swagger
|
|
6991
|
-
* /books:
|
|
6992
|
-
* get:
|
|
6993
|
-
* summary: List all books
|
|
6994
|
-
* description: Returns a list of all available books in the collection.
|
|
6995
|
-
* responses:
|
|
6996
|
-
* 200:
|
|
6997
|
-
* description: A list of books.
|
|
6998
|
-
* content:
|
|
6999
|
-
* application/json:
|
|
7000
|
-
* schema:
|
|
7001
|
-
* type: array
|
|
7002
|
-
* items:
|
|
7003
|
-
* type: string
|
|
7004
|
-
*/
|
|
7005
|
-
app.get([`/books`, `${rootPath}/books`], async (request, response) => {
|
|
7771
|
+
app.get(`/books`, async (request, response) => {
|
|
7006
7772
|
if (collection === null) {
|
|
7007
7773
|
response.status(500).send('No collection available');
|
|
7008
7774
|
return;
|
|
@@ -7012,30 +7778,7 @@
|
|
|
7012
7778
|
response.send(pipelines);
|
|
7013
7779
|
});
|
|
7014
7780
|
// TODO: [🧠] Is it secure / good idea to expose source codes of hosted books
|
|
7015
|
-
|
|
7016
|
-
* @swagger
|
|
7017
|
-
* /books/{bookId}:
|
|
7018
|
-
* get:
|
|
7019
|
-
* summary: Get book content
|
|
7020
|
-
* description: Returns the content of a specific book.
|
|
7021
|
-
* parameters:
|
|
7022
|
-
* - in: path
|
|
7023
|
-
* name: bookId
|
|
7024
|
-
* required: true
|
|
7025
|
-
* schema:
|
|
7026
|
-
* type: string
|
|
7027
|
-
* description: The ID of the book to retrieve.
|
|
7028
|
-
* responses:
|
|
7029
|
-
* 200:
|
|
7030
|
-
* description: The content of the book.
|
|
7031
|
-
* content:
|
|
7032
|
-
* text/markdown:
|
|
7033
|
-
* schema:
|
|
7034
|
-
* type: string
|
|
7035
|
-
* 404:
|
|
7036
|
-
* description: Book not found.
|
|
7037
|
-
*/
|
|
7038
|
-
app.get([`/books/*`, `${rootPath}/books/*`], async (request, response) => {
|
|
7781
|
+
app.get(`/books/*`, async (request, response) => {
|
|
7039
7782
|
try {
|
|
7040
7783
|
if (collection === null) {
|
|
7041
7784
|
response.status(500).send('No collection nor books available');
|
|
@@ -7054,9 +7797,7 @@
|
|
|
7054
7797
|
.send(source.content);
|
|
7055
7798
|
}
|
|
7056
7799
|
catch (error) {
|
|
7057
|
-
|
|
7058
|
-
throw error;
|
|
7059
|
-
}
|
|
7800
|
+
assertsError(error);
|
|
7060
7801
|
response
|
|
7061
7802
|
.status(404)
|
|
7062
7803
|
.send({ error: serializeError(error) });
|
|
@@ -7089,26 +7830,10 @@
|
|
|
7089
7830
|
};
|
|
7090
7831
|
}
|
|
7091
7832
|
}
|
|
7092
|
-
|
|
7093
|
-
|
|
7094
|
-
* /executions:
|
|
7095
|
-
* get:
|
|
7096
|
-
* summary: List all executions
|
|
7097
|
-
* description: Returns a list of all running execution tasks.
|
|
7098
|
-
* responses:
|
|
7099
|
-
* 200:
|
|
7100
|
-
* description: A list of execution tasks.
|
|
7101
|
-
* content:
|
|
7102
|
-
* application/json:
|
|
7103
|
-
* schema:
|
|
7104
|
-
* type: array
|
|
7105
|
-
* items:
|
|
7106
|
-
* type: object
|
|
7107
|
-
*/
|
|
7108
|
-
app.get([`/executions`, `${rootPath}/executions`], async (request, response) => {
|
|
7109
|
-
response.send(runningExecutionTasks.map((runningExecutionTask) => exportExecutionTask(runningExecutionTask, false)));
|
|
7833
|
+
app.get(`/executions`, async (request, response) => {
|
|
7834
|
+
response.send(runningExecutionTasks.map((runningExecutionTask) => exportExecutionTask(runningExecutionTask, false)) /* <- TODO: satisfies paths['/executions']['get']['responses']['200']['content']['application/json'] */);
|
|
7110
7835
|
});
|
|
7111
|
-
app.get(
|
|
7836
|
+
app.get(`/executions/last`, async (request, response) => {
|
|
7112
7837
|
// TODO: [🤬] Filter only for user
|
|
7113
7838
|
if (runningExecutionTasks.length === 0) {
|
|
7114
7839
|
response.status(404).send('No execution tasks found');
|
|
@@ -7117,7 +7842,7 @@
|
|
|
7117
7842
|
const lastExecutionTask = runningExecutionTasks[runningExecutionTasks.length - 1];
|
|
7118
7843
|
response.send(exportExecutionTask(lastExecutionTask, true));
|
|
7119
7844
|
});
|
|
7120
|
-
app.get(
|
|
7845
|
+
app.get(`/executions/:taskId`, async (request, response) => {
|
|
7121
7846
|
const { taskId } = request.params;
|
|
7122
7847
|
// TODO: [🤬] Filter only for user
|
|
7123
7848
|
const executionTask = runningExecutionTasks.find((executionTask) => executionTask.taskId === taskId);
|
|
@@ -7129,39 +7854,12 @@
|
|
|
7129
7854
|
}
|
|
7130
7855
|
response.send(exportExecutionTask(executionTask, true));
|
|
7131
7856
|
});
|
|
7132
|
-
|
|
7133
|
-
* @swagger
|
|
7134
|
-
* /executions/new:
|
|
7135
|
-
* post:
|
|
7136
|
-
* summary: Start a new execution
|
|
7137
|
-
* description: Starts a new execution task for a given pipeline.
|
|
7138
|
-
* requestBody:
|
|
7139
|
-
* required: true
|
|
7140
|
-
* content:
|
|
7141
|
-
* application/json:
|
|
7142
|
-
* schema:
|
|
7143
|
-
* type: object
|
|
7144
|
-
* properties:
|
|
7145
|
-
* pipelineUrl:
|
|
7146
|
-
* type: string
|
|
7147
|
-
* inputParameters:
|
|
7148
|
-
* type: object
|
|
7149
|
-
* identification:
|
|
7150
|
-
* type: object
|
|
7151
|
-
* responses:
|
|
7152
|
-
* 200:
|
|
7153
|
-
* description: The newly created execution task.
|
|
7154
|
-
* content:
|
|
7155
|
-
* application/json:
|
|
7156
|
-
* schema:
|
|
7157
|
-
* type: object
|
|
7158
|
-
* 400:
|
|
7159
|
-
* description: Invalid input.
|
|
7160
|
-
*/
|
|
7161
|
-
app.post([`/executions/new`, `${rootPath}/executions/new`], async (request, response) => {
|
|
7857
|
+
app.post(`/executions/new`, async (request, response) => {
|
|
7162
7858
|
try {
|
|
7163
7859
|
const { inputParameters, identification /* <- [🤬] */ } = request.body;
|
|
7164
|
-
const pipelineUrl = request.body
|
|
7860
|
+
const pipelineUrl = request.body
|
|
7861
|
+
.pipelineUrl /* <- TODO: as paths['/executions/new']['post']['requestBody']['content']['application/json'] */ ||
|
|
7862
|
+
request.body.book;
|
|
7165
7863
|
// TODO: [🧠] Check `pipelineUrl` and `inputParameters` here or it should be responsibility of `collection.getPipelineByUrl` and `pipelineExecutor`
|
|
7166
7864
|
const pipeline = await (collection === null || collection === void 0 ? void 0 : collection.getPipelineByUrl(pipelineUrl));
|
|
7167
7865
|
if (pipeline === undefined) {
|
|
@@ -7175,7 +7873,7 @@
|
|
|
7175
7873
|
await waitasecond.forTime(10);
|
|
7176
7874
|
// <- Note: Wait for a while to wait for quick responses or sudden but asynchronous errors
|
|
7177
7875
|
// <- TODO: Put this into configuration
|
|
7178
|
-
response.send(executionTask);
|
|
7876
|
+
response.send(executionTask /* <- TODO: satisfies paths['/executions/new']['post']['responses']['200']['content']['application/json'] */);
|
|
7179
7877
|
/*/
|
|
7180
7878
|
executionTask.asObservable().subscribe({
|
|
7181
7879
|
next(partialResult) {
|
|
@@ -7195,19 +7893,24 @@
|
|
|
7195
7893
|
*/
|
|
7196
7894
|
}
|
|
7197
7895
|
catch (error) {
|
|
7198
|
-
|
|
7199
|
-
throw error;
|
|
7200
|
-
}
|
|
7896
|
+
assertsError(error);
|
|
7201
7897
|
response.status(400).send({ error: serializeError(error) });
|
|
7202
7898
|
}
|
|
7203
7899
|
});
|
|
7900
|
+
/**
|
|
7901
|
+
* Catch-all handler for unmatched routes
|
|
7902
|
+
*/
|
|
7903
|
+
app.use((request, response) => {
|
|
7904
|
+
response.status(404).send(`URL "${request.originalUrl}" was not found on Promptbook server.`);
|
|
7905
|
+
});
|
|
7204
7906
|
const httpServer = http__default["default"].createServer(app);
|
|
7205
7907
|
const server = new socket_io.Server(httpServer, {
|
|
7206
|
-
path:
|
|
7207
|
-
transports: [
|
|
7908
|
+
path: '/socket.io',
|
|
7909
|
+
transports: ['polling', 'websocket' /*, <- TODO: [🌬] Allow to pass `transports`, add 'webtransport' */],
|
|
7208
7910
|
cors: {
|
|
7209
7911
|
origin: '*',
|
|
7210
7912
|
methods: ['GET', 'POST'],
|
|
7913
|
+
// <- TODO: [🌡] Allow to pass
|
|
7211
7914
|
},
|
|
7212
7915
|
});
|
|
7213
7916
|
server.on('connection', (socket) => {
|
|
@@ -7261,9 +7964,7 @@
|
|
|
7261
7964
|
socket.emit('prompt-response', { promptResult } /* <- Note: [🤛] */);
|
|
7262
7965
|
}
|
|
7263
7966
|
catch (error) {
|
|
7264
|
-
|
|
7265
|
-
throw error;
|
|
7266
|
-
}
|
|
7967
|
+
assertsError(error);
|
|
7267
7968
|
socket.emit('error', serializeError(error) /* <- Note: [🤛] */);
|
|
7268
7969
|
}
|
|
7269
7970
|
finally {
|
|
@@ -7285,9 +7986,7 @@
|
|
|
7285
7986
|
socket.emit('listModels-response', { models } /* <- Note: [🤛] */);
|
|
7286
7987
|
}
|
|
7287
7988
|
catch (error) {
|
|
7288
|
-
|
|
7289
|
-
throw error;
|
|
7290
|
-
}
|
|
7989
|
+
assertsError(error);
|
|
7291
7990
|
socket.emit('error', serializeError(error));
|
|
7292
7991
|
}
|
|
7293
7992
|
finally {
|
|
@@ -7308,9 +8007,7 @@
|
|
|
7308
8007
|
socket.emit('preparePipeline-response', { preparedPipeline } /* <- Note: [🤛] */);
|
|
7309
8008
|
}
|
|
7310
8009
|
catch (error) {
|
|
7311
|
-
|
|
7312
|
-
throw error;
|
|
7313
|
-
}
|
|
8010
|
+
assertsError(error);
|
|
7314
8011
|
socket.emit('error', serializeError(error));
|
|
7315
8012
|
// <- TODO: [🚋] There is a problem with the remote server handling errors and sending them back to the client
|
|
7316
8013
|
}
|
|
@@ -7358,8 +8055,7 @@
|
|
|
7358
8055
|
};
|
|
7359
8056
|
}
|
|
7360
8057
|
/**
|
|
7361
|
-
* TODO:
|
|
7362
|
-
* TODO: [👩🏾🤝🧑🏾] Allow to pass custom fetch function here - PromptbookFetch
|
|
8058
|
+
* TODO: [🌡] Add CORS and security - probbably via `helmet`
|
|
7363
8059
|
* TODO: Split this file into multiple functions - handler for each request
|
|
7364
8060
|
* TODO: Maybe use `$exportJson`
|
|
7365
8061
|
* TODO: [🧠][🛍] Maybe not `isAnonymous: boolean` BUT `mode: 'ANONYMOUS'|'COLLECTION'`
|