@promptbook/cli 0.89.0-8 → 0.89.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -11
- package/esm/index.es.js +969 -612
- package/esm/index.es.js.map +1 -1
- package/esm/typings/servers.d.ts +40 -0
- package/esm/typings/src/_packages/core.index.d.ts +12 -4
- package/esm/typings/src/_packages/remote-client.index.d.ts +6 -6
- package/esm/typings/src/_packages/remote-server.index.d.ts +6 -6
- package/esm/typings/src/_packages/types.index.d.ts +24 -14
- package/esm/typings/src/_packages/utils.index.d.ts +4 -0
- package/esm/typings/src/cli/cli-commands/login.d.ts +0 -1
- package/esm/typings/src/cli/common/$provideLlmToolsForCli.d.ts +16 -3
- package/esm/typings/src/cli/test/ptbk.d.ts +1 -1
- package/esm/typings/src/commands/EXPECT/expectCommandParser.d.ts +2 -0
- package/esm/typings/src/config.d.ts +10 -19
- package/esm/typings/src/errors/0-index.d.ts +8 -2
- package/esm/typings/src/errors/PipelineExecutionError.d.ts +1 -1
- package/esm/typings/src/errors/PromptbookFetchError.d.ts +9 -0
- package/esm/typings/src/errors/WrappedError.d.ts +10 -0
- package/esm/typings/src/errors/assertsError.d.ts +11 -0
- package/esm/typings/src/execution/PromptbookFetch.d.ts +1 -1
- package/esm/typings/src/formats/csv/utils/isValidCsvString.d.ts +9 -0
- package/esm/typings/src/formats/csv/utils/isValidCsvString.test.d.ts +1 -0
- package/esm/typings/src/formats/json/utils/isValidJsonString.d.ts +3 -0
- package/esm/typings/src/formats/xml/utils/isValidXmlString.d.ts +9 -0
- package/esm/typings/src/formats/xml/utils/isValidXmlString.test.d.ts +1 -0
- package/esm/typings/src/llm-providers/_common/register/$provideEnvFilename.d.ts +12 -0
- package/esm/typings/src/llm-providers/_common/register/$provideLlmToolsConfigurationFromEnv.d.ts +2 -8
- package/esm/typings/src/llm-providers/_common/register/$provideLlmToolsForTestingAndScriptsAndPlayground.d.ts +2 -0
- package/esm/typings/src/llm-providers/_common/register/$provideLlmToolsForWizzardOrCli.d.ts +15 -4
- package/esm/typings/src/llm-providers/_common/register/$provideLlmToolsFromEnv.d.ts +1 -0
- package/esm/typings/src/remote-server/openapi-types.d.ts +284 -0
- package/esm/typings/src/remote-server/openapi.d.ts +187 -0
- package/esm/typings/src/remote-server/socket-types/_subtypes/{PromptbookServer_Identification.d.ts → Identification.d.ts} +9 -3
- package/esm/typings/src/remote-server/socket-types/_subtypes/identificationToPromptbookToken.d.ts +11 -0
- package/esm/typings/src/remote-server/socket-types/_subtypes/promptbookTokenToIdentification.d.ts +10 -0
- package/esm/typings/src/remote-server/socket-types/listModels/PromptbookServer_ListModels_Request.d.ts +2 -2
- package/esm/typings/src/remote-server/socket-types/prepare/PromptbookServer_PreparePipeline_Request.d.ts +2 -2
- package/esm/typings/src/remote-server/socket-types/prompt/PromptbookServer_Prompt_Request.d.ts +2 -2
- package/esm/typings/src/remote-server/startRemoteServer.d.ts +1 -2
- package/esm/typings/src/remote-server/types/RemoteClientOptions.d.ts +2 -2
- package/esm/typings/src/remote-server/types/RemoteServerOptions.d.ts +57 -38
- package/esm/typings/src/scrapers/_common/utils/{scraperFetch.d.ts → promptbookFetch.d.ts} +2 -2
- package/esm/typings/src/storage/env-storage/$EnvStorage.d.ts +40 -0
- package/esm/typings/src/types/typeAliases.d.ts +26 -0
- package/package.json +15 -11
- package/umd/index.umd.js +972 -615
- package/umd/index.umd.js.map +1 -1
- package/esm/typings/src/cli/test/ptbk2.d.ts +0 -5
- package/esm/typings/src/playground/BrjappConnector.d.ts +0 -67
- package/esm/typings/src/playground/brjapp-api-schema.d.ts +0 -12879
package/umd/index.umd.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
(function (global, factory) {
|
|
2
|
-
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('colors'), require('commander'), require('spacetrim'), require('waitasecond'), require('prompts'), require('path'), require('fs/promises'), require('crypto-js/enc-hex'), require('crypto-js/sha256'), require('crypto'), require('socket.io-client'), require('rxjs'), require('
|
|
3
|
-
typeof define === 'function' && define.amd ? define(['exports', 'colors', 'commander', 'spacetrim', 'waitasecond', 'prompts', 'path', 'fs/promises', 'crypto-js/enc-hex', 'crypto-js/sha256', 'crypto', 'socket.io-client', 'rxjs', '
|
|
4
|
-
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global["promptbook-cli"] = {}, global.colors, global.commander, global.spaceTrim, global.waitasecond, global.prompts, global.path, global.promises, global.hexEncoder, global.sha256, global.crypto, global.socket_ioClient, global.rxjs, global.
|
|
5
|
-
})(this, (function (exports, colors, commander, spaceTrim, waitasecond, prompts, path, promises, hexEncoder, sha256, crypto, socket_ioClient, rxjs,
|
|
2
|
+
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('colors'), require('commander'), require('spacetrim'), require('waitasecond'), require('prompts'), require('path'), require('fs/promises'), require('dotenv'), require('crypto-js/enc-hex'), require('crypto-js/sha256'), require('crypto'), require('socket.io-client'), require('rxjs'), require('child_process'), require('jszip'), require('prettier'), require('prettier/parser-html'), require('papaparse'), require('crypto-js'), require('mime-types'), require('glob-promise'), require('moment'), require('express'), require('http'), require('socket.io'), require('express-openapi-validator'), require('swagger-ui-express'), require('@anthropic-ai/sdk'), require('@azure/openai'), require('openai'), require('@mozilla/readability'), require('jsdom'), require('showdown')) :
|
|
3
|
+
typeof define === 'function' && define.amd ? define(['exports', 'colors', 'commander', 'spacetrim', 'waitasecond', 'prompts', 'path', 'fs/promises', 'dotenv', 'crypto-js/enc-hex', 'crypto-js/sha256', 'crypto', 'socket.io-client', 'rxjs', 'child_process', 'jszip', 'prettier', 'prettier/parser-html', 'papaparse', 'crypto-js', 'mime-types', 'glob-promise', 'moment', 'express', 'http', 'socket.io', 'express-openapi-validator', 'swagger-ui-express', '@anthropic-ai/sdk', '@azure/openai', 'openai', '@mozilla/readability', 'jsdom', 'showdown'], factory) :
|
|
4
|
+
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global["promptbook-cli"] = {}, global.colors, global.commander, global.spaceTrim, global.waitasecond, global.prompts, global.path, global.promises, global.dotenv, global.hexEncoder, global.sha256, global.crypto, global.socket_ioClient, global.rxjs, global.child_process, global.JSZip, global.prettier, global.parserHtml, global.papaparse, global.cryptoJs, global.mimeTypes, global.glob, global.moment, global.express, global.http, global.socket_io, global.OpenApiValidator, global.swaggerUi, global.Anthropic, global.openai, global.OpenAI, global.readability, global.jsdom, global.showdown));
|
|
5
|
+
})(this, (function (exports, colors, commander, spaceTrim, waitasecond, prompts, path, promises, dotenv, hexEncoder, sha256, crypto, socket_ioClient, rxjs, child_process, JSZip, prettier, parserHtml, papaparse, cryptoJs, mimeTypes, glob, moment, express, http, socket_io, OpenApiValidator, swaggerUi, Anthropic, openai, OpenAI, readability, jsdom, showdown) { 'use strict';
|
|
6
6
|
|
|
7
7
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
8
8
|
|
|
@@ -28,16 +28,16 @@
|
|
|
28
28
|
var commander__default = /*#__PURE__*/_interopDefaultLegacy(commander);
|
|
29
29
|
var spaceTrim__default = /*#__PURE__*/_interopDefaultLegacy(spaceTrim);
|
|
30
30
|
var prompts__default = /*#__PURE__*/_interopDefaultLegacy(prompts);
|
|
31
|
+
var dotenv__namespace = /*#__PURE__*/_interopNamespace(dotenv);
|
|
31
32
|
var hexEncoder__default = /*#__PURE__*/_interopDefaultLegacy(hexEncoder);
|
|
32
33
|
var sha256__default = /*#__PURE__*/_interopDefaultLegacy(sha256);
|
|
33
|
-
var dotenv__namespace = /*#__PURE__*/_interopNamespace(dotenv);
|
|
34
34
|
var JSZip__default = /*#__PURE__*/_interopDefaultLegacy(JSZip);
|
|
35
35
|
var parserHtml__default = /*#__PURE__*/_interopDefaultLegacy(parserHtml);
|
|
36
36
|
var glob__default = /*#__PURE__*/_interopDefaultLegacy(glob);
|
|
37
37
|
var moment__default = /*#__PURE__*/_interopDefaultLegacy(moment);
|
|
38
38
|
var express__default = /*#__PURE__*/_interopDefaultLegacy(express);
|
|
39
39
|
var http__default = /*#__PURE__*/_interopDefaultLegacy(http);
|
|
40
|
-
var
|
|
40
|
+
var OpenApiValidator__namespace = /*#__PURE__*/_interopNamespace(OpenApiValidator);
|
|
41
41
|
var swaggerUi__default = /*#__PURE__*/_interopDefaultLegacy(swaggerUi);
|
|
42
42
|
var Anthropic__default = /*#__PURE__*/_interopDefaultLegacy(Anthropic);
|
|
43
43
|
var OpenAI__default = /*#__PURE__*/_interopDefaultLegacy(OpenAI);
|
|
@@ -56,12 +56,43 @@
|
|
|
56
56
|
* @generated
|
|
57
57
|
* @see https://github.com/webgptorg/promptbook
|
|
58
58
|
*/
|
|
59
|
-
const PROMPTBOOK_ENGINE_VERSION = '0.89.0
|
|
59
|
+
const PROMPTBOOK_ENGINE_VERSION = '0.89.0';
|
|
60
60
|
/**
|
|
61
61
|
* TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
|
|
62
62
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
63
63
|
*/
|
|
64
64
|
|
|
65
|
+
/**
|
|
66
|
+
* Available remote servers for the Promptbook
|
|
67
|
+
*
|
|
68
|
+
* @public exported from `@promptbook/core`
|
|
69
|
+
*/
|
|
70
|
+
const REMOTE_SERVER_URLS = [
|
|
71
|
+
{
|
|
72
|
+
title: 'Promptbook',
|
|
73
|
+
description: `Servers of Promptbook.studio`,
|
|
74
|
+
owner: 'AI Web, LLC <legal@ptbk.io> (https://www.ptbk.io/)',
|
|
75
|
+
isAnonymousModeAllowed: true,
|
|
76
|
+
urls: [
|
|
77
|
+
'https://promptbook.s5.ptbk.io/',
|
|
78
|
+
// Note: Servers 1-4 are not running
|
|
79
|
+
],
|
|
80
|
+
},
|
|
81
|
+
/*
|
|
82
|
+
Note: Working on older version of Promptbook and not supported anymore
|
|
83
|
+
{
|
|
84
|
+
title: 'Pavol Promptbook Server',
|
|
85
|
+
description: `Personal server of Pavol Hejný with simple testing server, DO NOT USE IT FOR PRODUCTION`,
|
|
86
|
+
owner: 'Pavol Hejný <pavol@ptbk.io> (https://www.pavolhejny.com/)',
|
|
87
|
+
isAnonymousModeAllowed: true,
|
|
88
|
+
urls: ['https://api.pavolhejny.com/promptbook'],
|
|
89
|
+
},
|
|
90
|
+
*/
|
|
91
|
+
];
|
|
92
|
+
/**
|
|
93
|
+
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
94
|
+
*/
|
|
95
|
+
|
|
65
96
|
/**
|
|
66
97
|
* Returns the same value that is passed as argument.
|
|
67
98
|
* No side effects.
|
|
@@ -116,6 +147,7 @@
|
|
|
116
147
|
* @public exported from `@promptbook/core`
|
|
117
148
|
*/
|
|
118
149
|
const CLAIM = `It's time for a paradigm shift. The future of software in plain English, French or Latin`;
|
|
150
|
+
// <- TODO: [🐊] Pick the best claim
|
|
119
151
|
/**
|
|
120
152
|
* When the title is not provided, the default title is used
|
|
121
153
|
*
|
|
@@ -146,6 +178,12 @@
|
|
|
146
178
|
* @private within the repository
|
|
147
179
|
*/
|
|
148
180
|
const GENERATOR_WARNING_BY_PROMPTBOOK_CLI = `⚠️ WARNING: This code has been generated by \`@promptbook/cli\` so that any manual changes will be overwritten`;
|
|
181
|
+
/**
|
|
182
|
+
* Warning message for the automatically generated sections of `.env` files
|
|
183
|
+
*
|
|
184
|
+
* @private within the repository
|
|
185
|
+
*/
|
|
186
|
+
const GENERATOR_WARNING_IN_ENV = `Note: Added by Promptbook`;
|
|
149
187
|
// <- TODO: [🧠] Better system for generator warnings - not always "code" and "by `@promptbook/cli`"
|
|
150
188
|
/**
|
|
151
189
|
* The maximum number of iterations for a loops
|
|
@@ -166,6 +204,7 @@
|
|
|
166
204
|
infinity: '(infinity; ∞)',
|
|
167
205
|
negativeInfinity: '(negative infinity; -∞)',
|
|
168
206
|
unserializable: '(unserializable value)',
|
|
207
|
+
circular: '(circular JSON)',
|
|
169
208
|
};
|
|
170
209
|
/**
|
|
171
210
|
* Small number limit
|
|
@@ -225,7 +264,7 @@
|
|
|
225
264
|
*/
|
|
226
265
|
const DEFAULT_BOOKS_DIRNAME = './books';
|
|
227
266
|
// <- TODO: [🕝] Make also `BOOKS_DIRNAME_ALTERNATIVES`
|
|
228
|
-
// TODO:
|
|
267
|
+
// TODO: Just `.promptbook` in config, hardcode subfolders like `download-cache` or `execution-cache`
|
|
229
268
|
/**
|
|
230
269
|
* Where to store the temporary downloads
|
|
231
270
|
*
|
|
@@ -281,11 +320,11 @@
|
|
|
281
320
|
ss: 3, // <- least number of seconds to be counted in seconds, minus 1. Must be set after setting the `s` unit or without setting the `s` unit.
|
|
282
321
|
};
|
|
283
322
|
/**
|
|
284
|
-
*
|
|
323
|
+
* Default remote server URL for the Promptbook
|
|
285
324
|
*
|
|
286
325
|
* @public exported from `@promptbook/core`
|
|
287
326
|
*/
|
|
288
|
-
const DEFAULT_REMOTE_SERVER_URL =
|
|
327
|
+
const DEFAULT_REMOTE_SERVER_URL = REMOTE_SERVER_URLS[0].urls[0];
|
|
289
328
|
// <- TODO: [🧜♂️]
|
|
290
329
|
/**
|
|
291
330
|
* @@@
|
|
@@ -419,6 +458,122 @@
|
|
|
419
458
|
* TODO: [🎺]
|
|
420
459
|
*/
|
|
421
460
|
|
|
461
|
+
/**
|
|
462
|
+
* Make error report URL for the given error
|
|
463
|
+
*
|
|
464
|
+
* @private private within the repository
|
|
465
|
+
*/
|
|
466
|
+
function getErrorReportUrl(error) {
|
|
467
|
+
const report = {
|
|
468
|
+
title: `🐜 Error report from ${NAME}`,
|
|
469
|
+
body: spaceTrim__default["default"]((block) => `
|
|
470
|
+
|
|
471
|
+
|
|
472
|
+
\`${error.name || 'Error'}\` has occurred in the [${NAME}], please look into it @${ADMIN_GITHUB_NAME}.
|
|
473
|
+
|
|
474
|
+
\`\`\`
|
|
475
|
+
${block(error.message || '(no error message)')}
|
|
476
|
+
\`\`\`
|
|
477
|
+
|
|
478
|
+
|
|
479
|
+
## More info:
|
|
480
|
+
|
|
481
|
+
- **Promptbook engine version:** ${PROMPTBOOK_ENGINE_VERSION}
|
|
482
|
+
- **Book language version:** ${BOOK_LANGUAGE_VERSION}
|
|
483
|
+
- **Time:** ${new Date().toISOString()}
|
|
484
|
+
|
|
485
|
+
<details>
|
|
486
|
+
<summary>Stack trace:</summary>
|
|
487
|
+
|
|
488
|
+
## Stack trace:
|
|
489
|
+
|
|
490
|
+
\`\`\`stacktrace
|
|
491
|
+
${block(error.stack || '(empty)')}
|
|
492
|
+
\`\`\`
|
|
493
|
+
</details>
|
|
494
|
+
|
|
495
|
+
`),
|
|
496
|
+
};
|
|
497
|
+
const reportUrl = new URL(`https://github.com/webgptorg/promptbook/issues/new`);
|
|
498
|
+
reportUrl.searchParams.set('labels', 'bug');
|
|
499
|
+
reportUrl.searchParams.set('assignees', ADMIN_GITHUB_NAME);
|
|
500
|
+
reportUrl.searchParams.set('title', report.title);
|
|
501
|
+
reportUrl.searchParams.set('body', report.body);
|
|
502
|
+
return reportUrl;
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
/**
|
|
506
|
+
* This error type indicates that the error should not happen and its last check before crashing with some other error
|
|
507
|
+
*
|
|
508
|
+
* @public exported from `@promptbook/core`
|
|
509
|
+
*/
|
|
510
|
+
class UnexpectedError extends Error {
|
|
511
|
+
constructor(message) {
|
|
512
|
+
super(spaceTrim.spaceTrim((block) => `
|
|
513
|
+
${block(message)}
|
|
514
|
+
|
|
515
|
+
Note: This error should not happen.
|
|
516
|
+
It's probbably a bug in the pipeline collection
|
|
517
|
+
|
|
518
|
+
Please report issue:
|
|
519
|
+
${block(getErrorReportUrl(new Error(message)).href)}
|
|
520
|
+
|
|
521
|
+
Or contact us on ${ADMIN_EMAIL}
|
|
522
|
+
|
|
523
|
+
`));
|
|
524
|
+
this.name = 'UnexpectedError';
|
|
525
|
+
Object.setPrototypeOf(this, UnexpectedError.prototype);
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
/**
|
|
530
|
+
* This error type indicates that somewhere in the code non-Error object was thrown and it was wrapped into the `WrappedError`
|
|
531
|
+
*
|
|
532
|
+
* @public exported from `@promptbook/core`
|
|
533
|
+
*/
|
|
534
|
+
class WrappedError extends Error {
|
|
535
|
+
constructor(whatWasThrown) {
|
|
536
|
+
const tag = `[🤮]`;
|
|
537
|
+
console.error(tag, whatWasThrown);
|
|
538
|
+
super(spaceTrim.spaceTrim(`
|
|
539
|
+
Non-Error object was thrown
|
|
540
|
+
|
|
541
|
+
Note: Look for ${tag} in the console for more details
|
|
542
|
+
Please report issue on ${ADMIN_EMAIL}
|
|
543
|
+
`));
|
|
544
|
+
this.name = 'WrappedError';
|
|
545
|
+
Object.setPrototypeOf(this, WrappedError.prototype);
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
/**
|
|
550
|
+
* Helper used in catch blocks to assert that the error is an instance of `Error`
|
|
551
|
+
*
|
|
552
|
+
* @param whatWasThrown Any object that was thrown
|
|
553
|
+
* @returns Nothing if the error is an instance of `Error`
|
|
554
|
+
* @throws `WrappedError` or `UnexpectedError` if the error is not standard
|
|
555
|
+
*
|
|
556
|
+
* @private within the repository
|
|
557
|
+
*/
|
|
558
|
+
function assertsError(whatWasThrown) {
|
|
559
|
+
// Case 1: Handle error which was rethrown as `WrappedError`
|
|
560
|
+
if (whatWasThrown instanceof WrappedError) {
|
|
561
|
+
const wrappedError = whatWasThrown;
|
|
562
|
+
throw wrappedError;
|
|
563
|
+
}
|
|
564
|
+
// Case 2: Handle unexpected errors
|
|
565
|
+
if (whatWasThrown instanceof UnexpectedError) {
|
|
566
|
+
const unexpectedError = whatWasThrown;
|
|
567
|
+
throw unexpectedError;
|
|
568
|
+
}
|
|
569
|
+
// Case 3: Handle standard errors - keep them up to consumer
|
|
570
|
+
if (whatWasThrown instanceof Error) {
|
|
571
|
+
return;
|
|
572
|
+
}
|
|
573
|
+
// Case 4: Handle non-standard errors - wrap them into `WrappedError` and throw
|
|
574
|
+
throw new WrappedError(whatWasThrown);
|
|
575
|
+
}
|
|
576
|
+
|
|
422
577
|
/**
|
|
423
578
|
* Wraps action to handle error console logging and exit process with error code
|
|
424
579
|
*
|
|
@@ -433,9 +588,7 @@
|
|
|
433
588
|
return process.exit(0);
|
|
434
589
|
}
|
|
435
590
|
catch (error) {
|
|
436
|
-
|
|
437
|
-
throw error;
|
|
438
|
-
}
|
|
591
|
+
assertsError(error);
|
|
439
592
|
// console.error(colors.bgRed(error.name));
|
|
440
593
|
console.error(colors__default["default"].red(/* error.stack || */ error.message));
|
|
441
594
|
return process.exit(1);
|
|
@@ -542,74 +695,6 @@
|
|
|
542
695
|
}
|
|
543
696
|
}
|
|
544
697
|
|
|
545
|
-
/**
|
|
546
|
-
* Make error report URL for the given error
|
|
547
|
-
*
|
|
548
|
-
* @private private within the repository
|
|
549
|
-
*/
|
|
550
|
-
function getErrorReportUrl(error) {
|
|
551
|
-
const report = {
|
|
552
|
-
title: `🐜 Error report from ${NAME}`,
|
|
553
|
-
body: spaceTrim__default["default"]((block) => `
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
\`${error.name || 'Error'}\` has occurred in the [${NAME}], please look into it @${ADMIN_GITHUB_NAME}.
|
|
557
|
-
|
|
558
|
-
\`\`\`
|
|
559
|
-
${block(error.message || '(no error message)')}
|
|
560
|
-
\`\`\`
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
## More info:
|
|
564
|
-
|
|
565
|
-
- **Promptbook engine version:** ${PROMPTBOOK_ENGINE_VERSION}
|
|
566
|
-
- **Book language version:** ${BOOK_LANGUAGE_VERSION}
|
|
567
|
-
- **Time:** ${new Date().toISOString()}
|
|
568
|
-
|
|
569
|
-
<details>
|
|
570
|
-
<summary>Stack trace:</summary>
|
|
571
|
-
|
|
572
|
-
## Stack trace:
|
|
573
|
-
|
|
574
|
-
\`\`\`stacktrace
|
|
575
|
-
${block(error.stack || '(empty)')}
|
|
576
|
-
\`\`\`
|
|
577
|
-
</details>
|
|
578
|
-
|
|
579
|
-
`),
|
|
580
|
-
};
|
|
581
|
-
const reportUrl = new URL(`https://github.com/webgptorg/promptbook/issues/new`);
|
|
582
|
-
reportUrl.searchParams.set('labels', 'bug');
|
|
583
|
-
reportUrl.searchParams.set('assignees', ADMIN_GITHUB_NAME);
|
|
584
|
-
reportUrl.searchParams.set('title', report.title);
|
|
585
|
-
reportUrl.searchParams.set('body', report.body);
|
|
586
|
-
return reportUrl;
|
|
587
|
-
}
|
|
588
|
-
|
|
589
|
-
/**
|
|
590
|
-
* This error type indicates that the error should not happen and its last check before crashing with some other error
|
|
591
|
-
*
|
|
592
|
-
* @public exported from `@promptbook/core`
|
|
593
|
-
*/
|
|
594
|
-
class UnexpectedError extends Error {
|
|
595
|
-
constructor(message) {
|
|
596
|
-
super(spaceTrim.spaceTrim((block) => `
|
|
597
|
-
${block(message)}
|
|
598
|
-
|
|
599
|
-
Note: This error should not happen.
|
|
600
|
-
It's probbably a bug in the pipeline collection
|
|
601
|
-
|
|
602
|
-
Please report issue:
|
|
603
|
-
${block(getErrorReportUrl(new Error(message)).href)}
|
|
604
|
-
|
|
605
|
-
Or contact us on ${ADMIN_EMAIL}
|
|
606
|
-
|
|
607
|
-
`));
|
|
608
|
-
this.name = 'UnexpectedError';
|
|
609
|
-
Object.setPrototypeOf(this, UnexpectedError.prototype);
|
|
610
|
-
}
|
|
611
|
-
}
|
|
612
|
-
|
|
613
698
|
/**
|
|
614
699
|
* @@@
|
|
615
700
|
*
|
|
@@ -897,119 +982,278 @@
|
|
|
897
982
|
`);
|
|
898
983
|
}
|
|
899
984
|
/**
|
|
900
|
-
* TODO: [®] DRY Register logic
|
|
901
|
-
* TODO: [🧠][⚛] Maybe pass env as argument
|
|
902
|
-
*/
|
|
903
|
-
|
|
904
|
-
/**
|
|
905
|
-
* Just says that the variable is not used but should be kept
|
|
906
|
-
* No side effects.
|
|
907
|
-
*
|
|
908
|
-
* Note: It can be usefull for:
|
|
909
|
-
*
|
|
910
|
-
* 1) Suppressing eager optimization of unused imports
|
|
911
|
-
* 2) Suppressing eslint errors of unused variables in the tests
|
|
912
|
-
* 3) Keeping the type of the variable for type testing
|
|
913
|
-
*
|
|
914
|
-
* @param value any values
|
|
915
|
-
* @returns void
|
|
916
|
-
* @private within the repository
|
|
985
|
+
* TODO: [®] DRY Register logic
|
|
986
|
+
* TODO: [🧠][⚛] Maybe pass env as argument
|
|
987
|
+
*/
|
|
988
|
+
|
|
989
|
+
/**
|
|
990
|
+
* Just says that the variable is not used but should be kept
|
|
991
|
+
* No side effects.
|
|
992
|
+
*
|
|
993
|
+
* Note: It can be usefull for:
|
|
994
|
+
*
|
|
995
|
+
* 1) Suppressing eager optimization of unused imports
|
|
996
|
+
* 2) Suppressing eslint errors of unused variables in the tests
|
|
997
|
+
* 3) Keeping the type of the variable for type testing
|
|
998
|
+
*
|
|
999
|
+
* @param value any values
|
|
1000
|
+
* @returns void
|
|
1001
|
+
* @private within the repository
|
|
1002
|
+
*/
|
|
1003
|
+
function keepUnused(...valuesToKeep) {
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
/**
|
|
1007
|
+
* Just says that the variable is not used directlys but should be kept because the existence of the variable is important
|
|
1008
|
+
*
|
|
1009
|
+
* @param value any values
|
|
1010
|
+
* @returns void
|
|
1011
|
+
* @private within the repository
|
|
1012
|
+
*/
|
|
1013
|
+
function $sideEffect(...sideEffectSubjects) {
|
|
1014
|
+
keepUnused(...sideEffectSubjects);
|
|
1015
|
+
}
|
|
1016
|
+
|
|
1017
|
+
/**
|
|
1018
|
+
* Convert identification to Promptbook token
|
|
1019
|
+
*
|
|
1020
|
+
* @param identification
|
|
1021
|
+
*
|
|
1022
|
+
* @public exported from `@promptbook/core`
|
|
1023
|
+
*/
|
|
1024
|
+
function identificationToPromptbookToken(identification) {
|
|
1025
|
+
const { appId, userId, userToken } = identification;
|
|
1026
|
+
const promptbookToken = `${appId}-${userId}-${userToken}`;
|
|
1027
|
+
return promptbookToken;
|
|
1028
|
+
}
|
|
1029
|
+
|
|
1030
|
+
/**
|
|
1031
|
+
* Convert Promptbook token to identification
|
|
1032
|
+
*
|
|
1033
|
+
* @param promptbookToken
|
|
1034
|
+
*
|
|
1035
|
+
* @public exported from `@promptbook/core`
|
|
1036
|
+
*/
|
|
1037
|
+
function promptbookTokenToIdentification(promptbookToken) {
|
|
1038
|
+
const [appId, userId, userToken] = promptbookToken.split('-');
|
|
1039
|
+
if (!appId || !userId || !userToken) {
|
|
1040
|
+
throw new Error(`Invalid promptbook token: ${promptbookToken}`);
|
|
1041
|
+
}
|
|
1042
|
+
const identification = {
|
|
1043
|
+
appId,
|
|
1044
|
+
userId,
|
|
1045
|
+
userToken,
|
|
1046
|
+
isAnonymous: false,
|
|
1047
|
+
};
|
|
1048
|
+
return identification;
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1051
|
+
/**
|
|
1052
|
+
* Just marks a place of place where should be something implemented
|
|
1053
|
+
* No side effects.
|
|
1054
|
+
*
|
|
1055
|
+
* Note: It can be usefull suppressing eslint errors of unused variables
|
|
1056
|
+
*
|
|
1057
|
+
* @param value any values
|
|
1058
|
+
* @returns void
|
|
1059
|
+
* @private within the repository
|
|
1060
|
+
*/
|
|
1061
|
+
function TODO_USE(...value) {
|
|
1062
|
+
}
|
|
1063
|
+
|
|
1064
|
+
/**
|
|
1065
|
+
* @@@
|
|
1066
|
+
*
|
|
1067
|
+
* @public exported from `@promptbook/node`
|
|
1068
|
+
*/
|
|
1069
|
+
function $provideFilesystemForNode(options) {
|
|
1070
|
+
if (!$isRunningInNode()) {
|
|
1071
|
+
throw new EnvironmentMismatchError('Function `$provideFilesystemForNode` works only in Node.js environment');
|
|
1072
|
+
}
|
|
1073
|
+
return {
|
|
1074
|
+
stat: promises.stat,
|
|
1075
|
+
access: promises.access,
|
|
1076
|
+
constants: promises.constants,
|
|
1077
|
+
readFile: promises.readFile,
|
|
1078
|
+
writeFile: promises.writeFile,
|
|
1079
|
+
readdir: promises.readdir,
|
|
1080
|
+
mkdir: promises.mkdir,
|
|
1081
|
+
};
|
|
1082
|
+
}
|
|
1083
|
+
/**
|
|
1084
|
+
* Note: [🟢] Code in this file should never be never released in packages that could be imported into browser environment
|
|
1085
|
+
*/
|
|
1086
|
+
|
|
1087
|
+
/**
|
|
1088
|
+
* Checks if the file exists
|
|
1089
|
+
*
|
|
1090
|
+
* @private within the repository
|
|
1091
|
+
*/
|
|
1092
|
+
async function isFileExisting(filename, fs) {
|
|
1093
|
+
const isReadAccessAllowed = await fs
|
|
1094
|
+
.access(filename, fs.constants.R_OK)
|
|
1095
|
+
.then(() => true)
|
|
1096
|
+
.catch(() => false);
|
|
1097
|
+
if (!isReadAccessAllowed) {
|
|
1098
|
+
return false;
|
|
1099
|
+
}
|
|
1100
|
+
const isFile = await fs
|
|
1101
|
+
.stat(filename)
|
|
1102
|
+
.then((fileStat) => fileStat.isFile())
|
|
1103
|
+
.catch(() => false);
|
|
1104
|
+
return isFile;
|
|
1105
|
+
}
|
|
1106
|
+
/**
|
|
1107
|
+
* Note: Not [~🟢~] because it is not directly dependent on `fs
|
|
1108
|
+
* TODO: [🐠] This can be a validator - with variants that return true/false and variants that throw errors with meaningless messages
|
|
1109
|
+
* TODO: [🖇] What about symlinks?
|
|
1110
|
+
*/
|
|
1111
|
+
|
|
1112
|
+
/**
|
|
1113
|
+
* Determines if the given path is a root path.
|
|
1114
|
+
*
|
|
1115
|
+
* Note: This does not check if the file exists only if the path is valid
|
|
1116
|
+
* @public exported from `@promptbook/utils`
|
|
1117
|
+
*/
|
|
1118
|
+
function isRootPath(value) {
|
|
1119
|
+
if (value === '/') {
|
|
1120
|
+
return true;
|
|
1121
|
+
}
|
|
1122
|
+
if (/^[A-Z]:\\$/i.test(value)) {
|
|
1123
|
+
return true;
|
|
1124
|
+
}
|
|
1125
|
+
return false;
|
|
1126
|
+
}
|
|
1127
|
+
/**
|
|
1128
|
+
* TODO: [🍏] Make for MacOS paths
|
|
1129
|
+
*/
|
|
1130
|
+
|
|
1131
|
+
/**
|
|
1132
|
+
* Provides the path to the `.env` file
|
|
1133
|
+
*
|
|
1134
|
+
* Note: `$` is used to indicate that this function is not a pure function - it uses filesystem to access `.env` file
|
|
1135
|
+
*
|
|
1136
|
+
* @private within the repository - for CLI utils
|
|
1137
|
+
*/
|
|
1138
|
+
async function $provideEnvFilename() {
|
|
1139
|
+
if (!$isRunningInNode()) {
|
|
1140
|
+
throw new EnvironmentMismatchError('Function `$provideEnvFilename` works only in Node.js environment');
|
|
1141
|
+
}
|
|
1142
|
+
const envFilePatterns = [
|
|
1143
|
+
'.env',
|
|
1144
|
+
'.env.test',
|
|
1145
|
+
'.env.local',
|
|
1146
|
+
'.env.development.local',
|
|
1147
|
+
'.env.development',
|
|
1148
|
+
'.env.production.local',
|
|
1149
|
+
'.env.production',
|
|
1150
|
+
'.env.prod.local',
|
|
1151
|
+
'.env.prod',
|
|
1152
|
+
// <- TODO: Maybe add more patterns
|
|
1153
|
+
];
|
|
1154
|
+
let rootDirname = process.cwd();
|
|
1155
|
+
up_to_root: for (let i = 0; i < LOOP_LIMIT; i++) {
|
|
1156
|
+
for (const pattern of envFilePatterns) {
|
|
1157
|
+
const envFilename = path.join(rootDirname, pattern);
|
|
1158
|
+
if (await isFileExisting(envFilename, $provideFilesystemForNode())) {
|
|
1159
|
+
$setUsedEnvFilename(envFilename);
|
|
1160
|
+
return envFilename;
|
|
1161
|
+
}
|
|
1162
|
+
}
|
|
1163
|
+
if (isRootPath(rootDirname)) {
|
|
1164
|
+
break up_to_root;
|
|
1165
|
+
}
|
|
1166
|
+
// Note: If the directory does not exist, try the parent directory
|
|
1167
|
+
rootDirname = path.join(rootDirname, '..');
|
|
1168
|
+
}
|
|
1169
|
+
return null;
|
|
1170
|
+
}
|
|
1171
|
+
/**
|
|
1172
|
+
* Note: [🟢] Code in this file should never be never released in packages that could be imported into browser environment
|
|
917
1173
|
*/
|
|
918
|
-
function keepUnused(...valuesToKeep) {
|
|
919
|
-
}
|
|
920
1174
|
|
|
921
1175
|
/**
|
|
922
|
-
*
|
|
1176
|
+
* Stores data in .env variables
|
|
923
1177
|
*
|
|
924
|
-
*
|
|
925
|
-
* @returns void
|
|
926
|
-
* @private within the repository
|
|
927
|
-
*/
|
|
928
|
-
function $sideEffect(...sideEffectSubjects) {
|
|
929
|
-
keepUnused(...sideEffectSubjects);
|
|
930
|
-
}
|
|
931
|
-
|
|
932
|
-
/**
|
|
933
|
-
* Stores data in memory (HEAP)
|
|
1178
|
+
* Note: `$` is used to indicate that this function is not a pure function - it uses filesystem to access `.env` file and also writes to `process.env`
|
|
934
1179
|
*
|
|
935
|
-
* @
|
|
1180
|
+
* @private within the repository - for CLI utils
|
|
936
1181
|
*/
|
|
937
|
-
class
|
|
1182
|
+
class $EnvStorage {
|
|
938
1183
|
constructor() {
|
|
939
|
-
this.
|
|
1184
|
+
this.envFilename = null;
|
|
1185
|
+
}
|
|
1186
|
+
async $provideOrCreateEnvFile() {
|
|
1187
|
+
if (this.envFilename !== null) {
|
|
1188
|
+
return this.envFilename;
|
|
1189
|
+
}
|
|
1190
|
+
let envFilename = await $provideEnvFilename();
|
|
1191
|
+
if (envFilename !== null) {
|
|
1192
|
+
this.envFilename = envFilename;
|
|
1193
|
+
return envFilename;
|
|
1194
|
+
}
|
|
1195
|
+
envFilename = path.join(process.cwd(), '.env');
|
|
1196
|
+
await promises.writeFile(envFilename, '# This file was initialized by Promptbook', 'utf-8');
|
|
1197
|
+
this.envFilename = envFilename;
|
|
1198
|
+
return envFilename;
|
|
1199
|
+
}
|
|
1200
|
+
transformKey(key) {
|
|
1201
|
+
return normalizeTo_SCREAMING_CASE(key);
|
|
940
1202
|
}
|
|
941
1203
|
/**
|
|
942
1204
|
* Returns the number of key/value pairs currently present in the list associated with the object.
|
|
943
1205
|
*/
|
|
944
1206
|
get length() {
|
|
945
|
-
|
|
1207
|
+
throw new NotYetImplementedError('Method `$EnvStorage.length` not implemented.');
|
|
946
1208
|
}
|
|
947
1209
|
/**
|
|
948
1210
|
* Empties the list associated with the object of all key/value pairs, if there are any.
|
|
949
1211
|
*/
|
|
950
1212
|
clear() {
|
|
951
|
-
|
|
1213
|
+
throw new NotYetImplementedError('Method `$EnvStorage.clear` not implemented.');
|
|
952
1214
|
}
|
|
953
1215
|
/**
|
|
954
1216
|
* Returns the current value associated with the given key, or null if the given key does not exist in the list associated with the object.
|
|
955
1217
|
*/
|
|
956
|
-
getItem(key) {
|
|
957
|
-
|
|
1218
|
+
async getItem(key) {
|
|
1219
|
+
dotenv__namespace.config({ path: await this.$provideOrCreateEnvFile() });
|
|
1220
|
+
return process.env[this.transformKey(key)] || null;
|
|
958
1221
|
}
|
|
959
1222
|
/**
|
|
960
1223
|
* Returns the name of the nth key in the list, or null if n is greater than or equal to the number of key/value pairs in the object.
|
|
961
1224
|
*/
|
|
962
1225
|
key(index) {
|
|
963
|
-
|
|
1226
|
+
throw new NotYetImplementedError('Method `$EnvStorage.key` not implemented.');
|
|
964
1227
|
}
|
|
965
1228
|
/**
|
|
966
1229
|
* Sets the value of the pair identified by key to value, creating a new key/value pair if none existed for key previously.
|
|
967
1230
|
*/
|
|
968
|
-
setItem(key, value) {
|
|
969
|
-
|
|
1231
|
+
async setItem(key, value) {
|
|
1232
|
+
const envFilename = await this.$provideOrCreateEnvFile();
|
|
1233
|
+
const envContent = await promises.readFile(envFilename, 'utf-8');
|
|
1234
|
+
const transformedKey = this.transformKey(key);
|
|
1235
|
+
const updatedEnvContent = envContent
|
|
1236
|
+
.split('\n')
|
|
1237
|
+
.filter((line) => !line.startsWith(`# ${GENERATOR_WARNING_IN_ENV}`)) // Remove GENERATOR_WARNING_IN_ENV
|
|
1238
|
+
.filter((line) => !line.startsWith(`${transformedKey}=`)) // Remove existing key if present
|
|
1239
|
+
.join('\n');
|
|
1240
|
+
const newEnvContent = spaceTrim__default["default"]((block) => `
|
|
1241
|
+
${block(updatedEnvContent)}
|
|
1242
|
+
|
|
1243
|
+
# ${GENERATOR_WARNING_IN_ENV}
|
|
1244
|
+
${transformedKey}=${JSON.stringify(value)}
|
|
1245
|
+
`);
|
|
1246
|
+
await promises.writeFile(envFilename, newEnvContent, 'utf-8');
|
|
970
1247
|
}
|
|
971
1248
|
/**
|
|
972
1249
|
* Removes the key/value pair with the given key from the list associated with the object, if a key/value pair with the given key exists.
|
|
973
1250
|
*/
|
|
974
1251
|
removeItem(key) {
|
|
975
|
-
|
|
976
|
-
}
|
|
977
|
-
}
|
|
978
|
-
|
|
979
|
-
/**
|
|
980
|
-
* Just marks a place of place where should be something implemented
|
|
981
|
-
* No side effects.
|
|
982
|
-
*
|
|
983
|
-
* Note: It can be usefull suppressing eslint errors of unused variables
|
|
984
|
-
*
|
|
985
|
-
* @param value any values
|
|
986
|
-
* @returns void
|
|
987
|
-
* @private within the repository
|
|
988
|
-
*/
|
|
989
|
-
function TODO_USE(...value) {
|
|
990
|
-
}
|
|
991
|
-
|
|
992
|
-
/**
|
|
993
|
-
* @@@
|
|
994
|
-
*
|
|
995
|
-
* @public exported from `@promptbook/node`
|
|
996
|
-
*/
|
|
997
|
-
function $provideFilesystemForNode(options) {
|
|
998
|
-
if (!$isRunningInNode()) {
|
|
999
|
-
throw new EnvironmentMismatchError('Function `$provideFilesystemForNode` works only in Node.js environment');
|
|
1252
|
+
throw new NotYetImplementedError('Method `$EnvStorage.removeItem` not implemented.');
|
|
1000
1253
|
}
|
|
1001
|
-
return {
|
|
1002
|
-
stat: promises.stat,
|
|
1003
|
-
access: promises.access,
|
|
1004
|
-
constants: promises.constants,
|
|
1005
|
-
readFile: promises.readFile,
|
|
1006
|
-
writeFile: promises.writeFile,
|
|
1007
|
-
readdir: promises.readdir,
|
|
1008
|
-
mkdir: promises.mkdir,
|
|
1009
|
-
};
|
|
1010
1254
|
}
|
|
1011
1255
|
/**
|
|
1012
|
-
*
|
|
1256
|
+
* TODO: Write file more securely - ensure that there can be no accidental overwriting of existing variables and other content
|
|
1013
1257
|
*/
|
|
1014
1258
|
|
|
1015
1259
|
/**
|
|
@@ -1145,9 +1389,7 @@
|
|
|
1145
1389
|
JSON.stringify(value); // <- TODO: [0]
|
|
1146
1390
|
}
|
|
1147
1391
|
catch (error) {
|
|
1148
|
-
|
|
1149
|
-
throw error;
|
|
1150
|
-
}
|
|
1392
|
+
assertsError(error);
|
|
1151
1393
|
throw new UnexpectedError(spaceTrim__default["default"]((block) => `
|
|
1152
1394
|
\`${name}\` is not serializable
|
|
1153
1395
|
|
|
@@ -1380,31 +1622,6 @@
|
|
|
1380
1622
|
* TODO: [🍙] Make some standard order of json properties
|
|
1381
1623
|
*/
|
|
1382
1624
|
|
|
1383
|
-
/**
|
|
1384
|
-
* Checks if the file exists
|
|
1385
|
-
*
|
|
1386
|
-
* @private within the repository
|
|
1387
|
-
*/
|
|
1388
|
-
async function isFileExisting(filename, fs) {
|
|
1389
|
-
const isReadAccessAllowed = await fs
|
|
1390
|
-
.access(filename, fs.constants.R_OK)
|
|
1391
|
-
.then(() => true)
|
|
1392
|
-
.catch(() => false);
|
|
1393
|
-
if (!isReadAccessAllowed) {
|
|
1394
|
-
return false;
|
|
1395
|
-
}
|
|
1396
|
-
const isFile = await fs
|
|
1397
|
-
.stat(filename)
|
|
1398
|
-
.then((fileStat) => fileStat.isFile())
|
|
1399
|
-
.catch(() => false);
|
|
1400
|
-
return isFile;
|
|
1401
|
-
}
|
|
1402
|
-
/**
|
|
1403
|
-
* Note: Not [~🟢~] because it is not directly dependent on `fs
|
|
1404
|
-
* TODO: [🐠] This can be a validator - with variants that return true/false and variants that throw errors with meaningless messages
|
|
1405
|
-
* TODO: [🖇] What about symlinks?
|
|
1406
|
-
*/
|
|
1407
|
-
|
|
1408
1625
|
/**
|
|
1409
1626
|
* Removes emojis from a string and fix whitespaces
|
|
1410
1627
|
*
|
|
@@ -2086,7 +2303,7 @@
|
|
|
2086
2303
|
}
|
|
2087
2304
|
}
|
|
2088
2305
|
/**
|
|
2089
|
-
* TODO:
|
|
2306
|
+
* TODO: [🧠][🌂] Add id to all errors
|
|
2090
2307
|
*/
|
|
2091
2308
|
|
|
2092
2309
|
/**
|
|
@@ -2115,6 +2332,19 @@
|
|
|
2115
2332
|
}
|
|
2116
2333
|
}
|
|
2117
2334
|
|
|
2335
|
+
/**
|
|
2336
|
+
* Error thrown when a fetch request fails
|
|
2337
|
+
*
|
|
2338
|
+
* @public exported from `@promptbook/core`
|
|
2339
|
+
*/
|
|
2340
|
+
class PromptbookFetchError extends Error {
|
|
2341
|
+
constructor(message) {
|
|
2342
|
+
super(message);
|
|
2343
|
+
this.name = 'PromptbookFetchError';
|
|
2344
|
+
Object.setPrototypeOf(this, PromptbookFetchError.prototype);
|
|
2345
|
+
}
|
|
2346
|
+
}
|
|
2347
|
+
|
|
2118
2348
|
/**
|
|
2119
2349
|
* Index of all custom errors
|
|
2120
2350
|
*
|
|
@@ -2135,7 +2365,10 @@
|
|
|
2135
2365
|
PipelineExecutionError,
|
|
2136
2366
|
PipelineLogicError,
|
|
2137
2367
|
PipelineUrlError,
|
|
2368
|
+
AuthenticationError,
|
|
2369
|
+
PromptbookFetchError,
|
|
2138
2370
|
UnexpectedError,
|
|
2371
|
+
WrappedError,
|
|
2139
2372
|
// TODO: [🪑]> VersionMismatchError,
|
|
2140
2373
|
};
|
|
2141
2374
|
/**
|
|
@@ -2152,7 +2385,6 @@
|
|
|
2152
2385
|
TypeError,
|
|
2153
2386
|
URIError,
|
|
2154
2387
|
AggregateError,
|
|
2155
|
-
AuthenticationError,
|
|
2156
2388
|
/*
|
|
2157
2389
|
Note: Not widely supported
|
|
2158
2390
|
> InternalError,
|
|
@@ -2210,17 +2442,31 @@
|
|
|
2210
2442
|
*/
|
|
2211
2443
|
async function createRemoteClient(options) {
|
|
2212
2444
|
const { remoteServerUrl } = options;
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2445
|
+
if (!isValidUrl(remoteServerUrl)) {
|
|
2446
|
+
throw new Error(`Invalid \`remoteServerUrl\`: "${remoteServerUrl}"`);
|
|
2447
|
+
}
|
|
2448
|
+
const remoteServerUrlParsed = new URL(remoteServerUrl);
|
|
2449
|
+
if (remoteServerUrlParsed.pathname !== '/' && remoteServerUrlParsed.pathname !== '') {
|
|
2450
|
+
remoteServerUrlParsed.pathname = '/';
|
|
2451
|
+
throw new Error(spaceTrim__default["default"]((block) => `
|
|
2452
|
+
Remote server requires root url \`/\`
|
|
2453
|
+
|
|
2454
|
+
You have provided \`remoteServerUrl\`:
|
|
2455
|
+
${block(remoteServerUrl)}
|
|
2456
|
+
|
|
2457
|
+
But something like this is expected:
|
|
2458
|
+
${block(remoteServerUrlParsed.href)}
|
|
2459
|
+
|
|
2460
|
+
Note: If you need to run multiple services on the same server, use 3rd or 4th degree subdomain
|
|
2461
|
+
|
|
2462
|
+
`));
|
|
2216
2463
|
}
|
|
2217
|
-
path = `${path}/socket.io`;
|
|
2218
2464
|
return new Promise((resolve, reject) => {
|
|
2219
2465
|
const socket = socket_ioClient.io(remoteServerUrl, {
|
|
2220
2466
|
retries: CONNECTION_RETRIES_LIMIT,
|
|
2221
2467
|
timeout: CONNECTION_TIMEOUT_MS,
|
|
2222
|
-
path,
|
|
2223
|
-
transports: [
|
|
2468
|
+
path: '/socket.io',
|
|
2469
|
+
transports: ['polling', 'websocket' /*, <- TODO: [🌬] Allow to pass `transports`, add 'webtransport' */],
|
|
2224
2470
|
});
|
|
2225
2471
|
// console.log('Connecting to', this.options.remoteServerUrl.href, { socket });
|
|
2226
2472
|
socket.on('connect', () => {
|
|
@@ -2345,6 +2591,53 @@
|
|
|
2345
2591
|
* TODO: [🧠] Maybe remove `@promptbook/remote-client` and just use `@promptbook/core`
|
|
2346
2592
|
*/
|
|
2347
2593
|
|
|
2594
|
+
/**
|
|
2595
|
+
* Stores data in memory (HEAP)
|
|
2596
|
+
*
|
|
2597
|
+
* @public exported from `@promptbook/core`
|
|
2598
|
+
*/
|
|
2599
|
+
class MemoryStorage {
|
|
2600
|
+
constructor() {
|
|
2601
|
+
this.storage = {};
|
|
2602
|
+
}
|
|
2603
|
+
/**
|
|
2604
|
+
* Returns the number of key/value pairs currently present in the list associated with the object.
|
|
2605
|
+
*/
|
|
2606
|
+
get length() {
|
|
2607
|
+
return Object.keys(this.storage).length;
|
|
2608
|
+
}
|
|
2609
|
+
/**
|
|
2610
|
+
* Empties the list associated with the object of all key/value pairs, if there are any.
|
|
2611
|
+
*/
|
|
2612
|
+
clear() {
|
|
2613
|
+
this.storage = {};
|
|
2614
|
+
}
|
|
2615
|
+
/**
|
|
2616
|
+
* Returns the current value associated with the given key, or null if the given key does not exist in the list associated with the object.
|
|
2617
|
+
*/
|
|
2618
|
+
getItem(key) {
|
|
2619
|
+
return this.storage[key] || null;
|
|
2620
|
+
}
|
|
2621
|
+
/**
|
|
2622
|
+
* Returns the name of the nth key in the list, or null if n is greater than or equal to the number of key/value pairs in the object.
|
|
2623
|
+
*/
|
|
2624
|
+
key(index) {
|
|
2625
|
+
return Object.keys(this.storage)[index] || null;
|
|
2626
|
+
}
|
|
2627
|
+
/**
|
|
2628
|
+
* Sets the value of the pair identified by key to value, creating a new key/value pair if none existed for key previously.
|
|
2629
|
+
*/
|
|
2630
|
+
setItem(key, value) {
|
|
2631
|
+
this.storage[key] = value;
|
|
2632
|
+
}
|
|
2633
|
+
/**
|
|
2634
|
+
* Removes the key/value pair with the given key from the list associated with the object, if a key/value pair with the given key exists.
|
|
2635
|
+
*/
|
|
2636
|
+
removeItem(key) {
|
|
2637
|
+
delete this.storage[key];
|
|
2638
|
+
}
|
|
2639
|
+
}
|
|
2640
|
+
|
|
2348
2641
|
/**
|
|
2349
2642
|
* Simple wrapper `new Date().toISOString()`
|
|
2350
2643
|
*
|
|
@@ -2631,29 +2924,11 @@
|
|
|
2631
2924
|
* TODO: [👷♂️] @@@ Manual about construction of llmTools
|
|
2632
2925
|
*/
|
|
2633
2926
|
|
|
2634
|
-
/**
|
|
2635
|
-
* Determines if the given path is a root path.
|
|
2636
|
-
*
|
|
2637
|
-
* Note: This does not check if the file exists only if the path is valid
|
|
2638
|
-
* @public exported from `@promptbook/utils`
|
|
2639
|
-
*/
|
|
2640
|
-
function isRootPath(value) {
|
|
2641
|
-
if (value === '/') {
|
|
2642
|
-
return true;
|
|
2643
|
-
}
|
|
2644
|
-
if (/^[A-Z]:\\$/i.test(value)) {
|
|
2645
|
-
return true;
|
|
2646
|
-
}
|
|
2647
|
-
return false;
|
|
2648
|
-
}
|
|
2649
|
-
/**
|
|
2650
|
-
* TODO: [🍏] Make for MacOS paths
|
|
2651
|
-
*/
|
|
2652
|
-
|
|
2653
2927
|
/**
|
|
2654
2928
|
* @@@
|
|
2655
2929
|
*
|
|
2656
2930
|
* @@@ .env
|
|
2931
|
+
* Note: `$` is used to indicate that this function is not a pure function - it uses filesystem to access `.env` file
|
|
2657
2932
|
*
|
|
2658
2933
|
* It looks for environment variables:
|
|
2659
2934
|
* - `process.env.OPENAI_API_KEY`
|
|
@@ -2667,33 +2942,9 @@
|
|
|
2667
2942
|
if (!$isRunningInNode()) {
|
|
2668
2943
|
throw new EnvironmentMismatchError('Function `$provideLlmToolsFromEnv` works only in Node.js environment');
|
|
2669
2944
|
}
|
|
2670
|
-
const
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
'.env.local',
|
|
2674
|
-
'.env.development.local',
|
|
2675
|
-
'.env.development',
|
|
2676
|
-
'.env.production.local',
|
|
2677
|
-
'.env.production',
|
|
2678
|
-
'.env.prod.local',
|
|
2679
|
-
'.env.prod',
|
|
2680
|
-
// <- TODO: Maybe add more patterns
|
|
2681
|
-
];
|
|
2682
|
-
let rootDirname = process.cwd();
|
|
2683
|
-
up_to_root: for (let i = 0; i < LOOP_LIMIT; i++) {
|
|
2684
|
-
for (const pattern of envFilePatterns) {
|
|
2685
|
-
const envFilename = path.join(rootDirname, pattern);
|
|
2686
|
-
if (await isFileExisting(envFilename, $provideFilesystemForNode())) {
|
|
2687
|
-
$setUsedEnvFilename(envFilename);
|
|
2688
|
-
dotenv__namespace.config({ path: envFilename });
|
|
2689
|
-
break up_to_root;
|
|
2690
|
-
}
|
|
2691
|
-
}
|
|
2692
|
-
if (isRootPath(rootDirname)) {
|
|
2693
|
-
break up_to_root;
|
|
2694
|
-
}
|
|
2695
|
-
// Note: If the directory does not exist, try the parent directory
|
|
2696
|
-
rootDirname = path.join(rootDirname, '..');
|
|
2945
|
+
const envFilepath = await $provideEnvFilename();
|
|
2946
|
+
if (envFilepath !== null) {
|
|
2947
|
+
dotenv__namespace.config({ path: envFilepath });
|
|
2697
2948
|
}
|
|
2698
2949
|
const llmToolsConfiguration = $llmToolsMetadataRegister
|
|
2699
2950
|
.list()
|
|
@@ -2702,15 +2953,8 @@
|
|
|
2702
2953
|
return llmToolsConfiguration;
|
|
2703
2954
|
}
|
|
2704
2955
|
/**
|
|
2705
|
-
* TODO: [🧠][🪁] Maybe do allow to do auto-install if package not registered and not found
|
|
2706
|
-
* TODO: Add Azure OpenAI
|
|
2707
|
-
* TODO: [🧠][🍛]
|
|
2708
|
-
* TODO: [🧠] Is there some meaningfull way how to test this util
|
|
2709
2956
|
* Note: [🟢] Code in this file should never be never released in packages that could be imported into browser environment
|
|
2710
|
-
|
|
2711
|
-
* TODO: This should be maybe not under `_common` but under `utils`
|
|
2712
|
-
* TODO: [🧠][⚛] Maybe pass env as argument
|
|
2713
|
-
* TODO: [®] DRY Register logic */
|
|
2957
|
+
*/
|
|
2714
2958
|
|
|
2715
2959
|
/**
|
|
2716
2960
|
* Multiple LLM Execution Tools is a proxy server that uses multiple execution tools internally and exposes the executor interface externally.
|
|
@@ -2806,14 +3050,15 @@
|
|
|
2806
3050
|
}
|
|
2807
3051
|
}
|
|
2808
3052
|
catch (error) {
|
|
2809
|
-
|
|
3053
|
+
assertsError(error);
|
|
3054
|
+
if (error instanceof UnexpectedError) {
|
|
2810
3055
|
throw error;
|
|
2811
3056
|
}
|
|
2812
3057
|
errors.push({ llmExecutionTools, error });
|
|
2813
3058
|
}
|
|
2814
3059
|
}
|
|
2815
3060
|
if (errors.length === 1) {
|
|
2816
|
-
throw errors[0];
|
|
3061
|
+
throw errors[0].error;
|
|
2817
3062
|
}
|
|
2818
3063
|
else if (errors.length > 1) {
|
|
2819
3064
|
throw new PipelineExecutionError(
|
|
@@ -2960,6 +3205,7 @@
|
|
|
2960
3205
|
* Note: This function is not cached, every call creates new instance of `MultipleLlmExecutionTools`
|
|
2961
3206
|
*
|
|
2962
3207
|
* @@@ .env
|
|
3208
|
+
* Note: `$` is used to indicate that this function is not a pure function - it uses filesystem to access `.env` file
|
|
2963
3209
|
*
|
|
2964
3210
|
* It looks for environment variables:
|
|
2965
3211
|
* - `process.env.OPENAI_API_KEY`
|
|
@@ -3004,6 +3250,8 @@
|
|
|
3004
3250
|
/**
|
|
3005
3251
|
* Returns LLM tools for CLI
|
|
3006
3252
|
*
|
|
3253
|
+
* Note: `$` is used to indicate that this function is not a pure function - it uses filesystem to access `.env` file and also writes this .env file
|
|
3254
|
+
*
|
|
3007
3255
|
* @private within the repository - for CLI utils
|
|
3008
3256
|
*/
|
|
3009
3257
|
async function $provideLlmToolsForWizzardOrCli(options) {
|
|
@@ -3011,16 +3259,27 @@
|
|
|
3011
3259
|
throw new EnvironmentMismatchError('Function `$provideLlmToolsForWizzardOrCli` works only in Node.js environment');
|
|
3012
3260
|
}
|
|
3013
3261
|
options = options !== null && options !== void 0 ? options : { strategy: 'BRING_YOUR_OWN_KEYS' };
|
|
3014
|
-
const { strategy, isCacheReloaded } = options;
|
|
3262
|
+
const { isLoginloaded, strategy, isCacheReloaded } = options;
|
|
3015
3263
|
let llmExecutionTools;
|
|
3016
3264
|
if (strategy === 'REMOTE_SERVER') {
|
|
3017
3265
|
const { remoteServerUrl = DEFAULT_REMOTE_SERVER_URL, loginPrompt } = options;
|
|
3018
|
-
const storage = new
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
3266
|
+
const storage = new $EnvStorage();
|
|
3267
|
+
let key = `PROMPTBOOK_TOKEN`;
|
|
3268
|
+
if (remoteServerUrl !== DEFAULT_REMOTE_SERVER_URL) {
|
|
3269
|
+
key = `${key}_${remoteServerUrl.replace(/^https?:\/\//i, '')}`;
|
|
3270
|
+
}
|
|
3271
|
+
let identification = null;
|
|
3272
|
+
let promptbookToken = await storage.getItem(key);
|
|
3273
|
+
if (promptbookToken === null || isLoginloaded) {
|
|
3022
3274
|
identification = await loginPrompt();
|
|
3023
|
-
|
|
3275
|
+
// Note: When login prompt fails, `process.exit(1)` is called so no need to check for null
|
|
3276
|
+
if (identification.isAnonymous === false) {
|
|
3277
|
+
promptbookToken = identificationToPromptbookToken(identification);
|
|
3278
|
+
await storage.setItem(key, promptbookToken);
|
|
3279
|
+
}
|
|
3280
|
+
}
|
|
3281
|
+
else {
|
|
3282
|
+
identification = promptbookTokenToIdentification(promptbookToken);
|
|
3024
3283
|
}
|
|
3025
3284
|
llmExecutionTools = new RemoteLlmExecutionTools({
|
|
3026
3285
|
remoteServerUrl,
|
|
@@ -3044,11 +3303,42 @@
|
|
|
3044
3303
|
});
|
|
3045
3304
|
}
|
|
3046
3305
|
/**
|
|
3047
|
-
* Note: [🟢] Code in this file should never be never released in packages that could be imported into browser environment
|
|
3048
|
-
* TODO: [👷♂️] @@@ Manual about construction of llmTools
|
|
3049
|
-
* TODO: [🥃] Allow `ptbk make` without llm tools
|
|
3050
|
-
* TODO: This should be maybe not under `_common` but under `utils-internal` / `utils/internal`
|
|
3051
|
-
* TODO: [®] DRY Register logic
|
|
3306
|
+
* Note: [🟢] Code in this file should never be never released in packages that could be imported into browser environment
|
|
3307
|
+
* TODO: [👷♂️] @@@ Manual about construction of llmTools
|
|
3308
|
+
* TODO: [🥃] Allow `ptbk make` without llm tools
|
|
3309
|
+
* TODO: This should be maybe not under `_common` but under `utils-internal` / `utils/internal`
|
|
3310
|
+
* TODO: [®] DRY Register logic
|
|
3311
|
+
*/
|
|
3312
|
+
|
|
3313
|
+
/**
|
|
3314
|
+
* The built-in `fetch' function with a lightweight error handling wrapper as default fetch function used in Promptbook scrapers
|
|
3315
|
+
*
|
|
3316
|
+
* @public exported from `@promptbook/core`
|
|
3317
|
+
*/
|
|
3318
|
+
const promptbookFetch = async (urlOrRequest, init) => {
|
|
3319
|
+
try {
|
|
3320
|
+
return await fetch(urlOrRequest, init);
|
|
3321
|
+
}
|
|
3322
|
+
catch (error) {
|
|
3323
|
+
assertsError(error);
|
|
3324
|
+
let url;
|
|
3325
|
+
if (typeof urlOrRequest === 'string') {
|
|
3326
|
+
url = urlOrRequest;
|
|
3327
|
+
}
|
|
3328
|
+
else if (urlOrRequest instanceof Request) {
|
|
3329
|
+
url = urlOrRequest.url;
|
|
3330
|
+
}
|
|
3331
|
+
throw new PromptbookFetchError(spaceTrim__default["default"]((block) => `
|
|
3332
|
+
Can not fetch "${url}"
|
|
3333
|
+
|
|
3334
|
+
Fetch error:
|
|
3335
|
+
${block(error.message)}
|
|
3336
|
+
|
|
3337
|
+
`));
|
|
3338
|
+
}
|
|
3339
|
+
};
|
|
3340
|
+
/**
|
|
3341
|
+
* TODO: [🧠] Maybe rename because it is not used only for scrapers but also in `$getCompiledBook`
|
|
3052
3342
|
*/
|
|
3053
3343
|
|
|
3054
3344
|
/**
|
|
@@ -3069,8 +3359,8 @@
|
|
|
3069
3359
|
/**
|
|
3070
3360
|
* @private utility of CLI
|
|
3071
3361
|
*/
|
|
3072
|
-
function $provideLlmToolsForCli(options) {
|
|
3073
|
-
const { cliOptions: {
|
|
3362
|
+
async function $provideLlmToolsForCli(options) {
|
|
3363
|
+
const { isLoginloaded, cliOptions: {
|
|
3074
3364
|
/* TODO: Use verbose: isVerbose, */ interactive: isInteractive, provider, remoteServerUrl: remoteServerUrlRaw, }, } = options;
|
|
3075
3365
|
let strategy;
|
|
3076
3366
|
if (/^b/i.test(provider)) {
|
|
@@ -3084,7 +3374,11 @@
|
|
|
3084
3374
|
process.exit(1);
|
|
3085
3375
|
}
|
|
3086
3376
|
if (strategy === 'BRING_YOUR_OWN_KEYS') {
|
|
3087
|
-
|
|
3377
|
+
if (isLoginloaded) {
|
|
3378
|
+
throw new UnexpectedError(`\`$provideLlmToolsForCli\` isLoginloaded is not supported for strategy "BRING_YOUR_OWN_KEYS"`);
|
|
3379
|
+
}
|
|
3380
|
+
const llm = await $provideLlmToolsForWizzardOrCli({ strategy, ...options });
|
|
3381
|
+
return { strategy, llm };
|
|
3088
3382
|
}
|
|
3089
3383
|
else if (strategy === 'REMOTE_SERVER') {
|
|
3090
3384
|
if (!isValidUrl(remoteServerUrlRaw)) {
|
|
@@ -3092,7 +3386,8 @@
|
|
|
3092
3386
|
process.exit(1);
|
|
3093
3387
|
}
|
|
3094
3388
|
const remoteServerUrl = remoteServerUrlRaw.endsWith('/') ? remoteServerUrlRaw.slice(0, -1) : remoteServerUrlRaw;
|
|
3095
|
-
|
|
3389
|
+
const llm = await $provideLlmToolsForWizzardOrCli({
|
|
3390
|
+
isLoginloaded,
|
|
3096
3391
|
strategy,
|
|
3097
3392
|
appId: CLI_APP_ID,
|
|
3098
3393
|
remoteServerUrl,
|
|
@@ -3102,6 +3397,10 @@
|
|
|
3102
3397
|
console.log(colors__default["default"].red(`You can not login to remote server in non-interactive mode`));
|
|
3103
3398
|
process.exit(1);
|
|
3104
3399
|
}
|
|
3400
|
+
console.info(colors__default["default"].cyan(spaceTrim__default["default"](`
|
|
3401
|
+
You will be logged in to ${remoteServerUrl}
|
|
3402
|
+
If you don't have an account, it will be created automatically.
|
|
3403
|
+
`)));
|
|
3105
3404
|
const { username, password } = await prompts__default["default"]([
|
|
3106
3405
|
{
|
|
3107
3406
|
type: 'text',
|
|
@@ -3119,7 +3418,8 @@
|
|
|
3119
3418
|
},
|
|
3120
3419
|
]);
|
|
3121
3420
|
const loginUrl = `${remoteServerUrl}/login`;
|
|
3122
|
-
|
|
3421
|
+
// TODO: [🧠] Should we use normal `fetch` or `scraperFetch`
|
|
3422
|
+
const response = await promptbookFetch(loginUrl, {
|
|
3123
3423
|
method: 'POST',
|
|
3124
3424
|
headers: {
|
|
3125
3425
|
'Content-Type': 'application/json',
|
|
@@ -3130,13 +3430,6 @@
|
|
|
3130
3430
|
password,
|
|
3131
3431
|
}),
|
|
3132
3432
|
});
|
|
3133
|
-
console.log('!!!', {
|
|
3134
|
-
loginUrl,
|
|
3135
|
-
username,
|
|
3136
|
-
password,
|
|
3137
|
-
// type: response.type,
|
|
3138
|
-
// text: await response.text(),
|
|
3139
|
-
});
|
|
3140
3433
|
const { isSuccess, message, error, identification } = (await response.json());
|
|
3141
3434
|
if (message) {
|
|
3142
3435
|
if (isSuccess) {
|
|
@@ -3158,6 +3451,7 @@
|
|
|
3158
3451
|
return identification;
|
|
3159
3452
|
},
|
|
3160
3453
|
});
|
|
3454
|
+
return { strategy, llm };
|
|
3161
3455
|
}
|
|
3162
3456
|
else {
|
|
3163
3457
|
throw new UnexpectedError(`\`$provideLlmToolsForCli\` wrong strategy "${strategy}"`);
|
|
@@ -3179,11 +3473,12 @@
|
|
|
3179
3473
|
listModelsCommand.alias('models');
|
|
3180
3474
|
listModelsCommand.alias('llm');
|
|
3181
3475
|
listModelsCommand.action(handleActionErrors(async (cliOptions) => {
|
|
3182
|
-
|
|
3183
|
-
// TODO: !!!!!! Not relevant for remote server and also for `about` command
|
|
3184
|
-
const llm = await $provideLlmToolsForCli({ cliOptions });
|
|
3476
|
+
const { strategy, llm } = await $provideLlmToolsForCli({ cliOptions });
|
|
3185
3477
|
$sideEffect(llm);
|
|
3186
3478
|
// <- Note: Providing LLM tools will make a side effect of registering all available LLM tools to show the message
|
|
3479
|
+
if (strategy !== 'BRING_YOUR_OWN_KEYS') {
|
|
3480
|
+
console.warn(colors__default["default"].yellow(`You are using --strategy ${strategy} but models listed below are relevant for --strategy BRING_YOUR_OWN_KEYS`));
|
|
3481
|
+
}
|
|
3187
3482
|
console.info($registeredLlmToolsMessage());
|
|
3188
3483
|
return process.exit(0);
|
|
3189
3484
|
}));
|
|
@@ -3366,9 +3661,7 @@
|
|
|
3366
3661
|
return result.trim();
|
|
3367
3662
|
}
|
|
3368
3663
|
catch (error) {
|
|
3369
|
-
|
|
3370
|
-
throw error;
|
|
3371
|
-
}
|
|
3664
|
+
assertsError(error);
|
|
3372
3665
|
return null;
|
|
3373
3666
|
}
|
|
3374
3667
|
}
|
|
@@ -3423,9 +3716,7 @@
|
|
|
3423
3716
|
return result.trim() + toExec;
|
|
3424
3717
|
}
|
|
3425
3718
|
catch (error) {
|
|
3426
|
-
|
|
3427
|
-
throw error;
|
|
3428
|
-
}
|
|
3719
|
+
assertsError(error);
|
|
3429
3720
|
return null;
|
|
3430
3721
|
}
|
|
3431
3722
|
}
|
|
@@ -3456,9 +3747,7 @@
|
|
|
3456
3747
|
throw new Error(`Can not locate app ${appName} on Windows.`);
|
|
3457
3748
|
}
|
|
3458
3749
|
catch (error) {
|
|
3459
|
-
|
|
3460
|
-
throw error;
|
|
3461
|
-
}
|
|
3750
|
+
assertsError(error);
|
|
3462
3751
|
return null;
|
|
3463
3752
|
}
|
|
3464
3753
|
}
|
|
@@ -3717,6 +4006,7 @@
|
|
|
3717
4006
|
`));
|
|
3718
4007
|
listModelsCommand.alias('scrapers');
|
|
3719
4008
|
listModelsCommand.action(handleActionErrors(async () => {
|
|
4009
|
+
// TODO: [🌞] Do not allow on REMOTE_SERVER strategy
|
|
3720
4010
|
const scrapers = await $provideScrapersForNode({});
|
|
3721
4011
|
const executables = await $provideExecutablesForNode();
|
|
3722
4012
|
console.info(spaceTrim__default["default"]((block) => `
|
|
@@ -3752,42 +4042,20 @@
|
|
|
3752
4042
|
loginCommand.description(spaceTrim__default["default"](`
|
|
3753
4043
|
Login to the remote Promptbook server
|
|
3754
4044
|
`));
|
|
3755
|
-
loginCommand.action(handleActionErrors(async () => {
|
|
3756
|
-
//
|
|
3757
|
-
|
|
3758
|
-
|
|
3759
|
-
|
|
3760
|
-
|
|
3761
|
-
|
|
3762
|
-
|
|
3763
|
-
{
|
|
3764
|
-
type: 'text',
|
|
3765
|
-
name: 'email',
|
|
3766
|
-
message: 'Enter your email:',
|
|
3767
|
-
validate: (value) => (isValidEmail(value) ? true : 'Valid email is required'),
|
|
3768
|
-
},
|
|
3769
|
-
{
|
|
3770
|
-
type: 'password',
|
|
3771
|
-
name: 'password',
|
|
3772
|
-
message: 'Enter your password:',
|
|
3773
|
-
validate: (value) => value.length /* <- TODO: [🧠] Better password validation */ > 0 ? true : 'Password is required',
|
|
4045
|
+
loginCommand.action(handleActionErrors(async (cliOptions) => {
|
|
4046
|
+
// Note: Not interested in return value of this function but the side effect of logging in
|
|
4047
|
+
await $provideLlmToolsForCli({
|
|
4048
|
+
isLoginloaded: true,
|
|
4049
|
+
cliOptions: {
|
|
4050
|
+
...cliOptions,
|
|
4051
|
+
strategy: 'REMOTE_SERVER', // <- Note: Overriding strategy to `REMOTE_SERVER`
|
|
4052
|
+
// TODO: Do not allow flag `--strategy` in `login` command at all
|
|
3774
4053
|
},
|
|
3775
|
-
|
|
3776
|
-
TODO_USE(email, password);
|
|
3777
|
-
await waitasecond.forTime(1000);
|
|
3778
|
-
console.error(colors__default["default"].green(spaceTrim__default["default"](`
|
|
3779
|
-
Your account ${email} was successfully created.
|
|
3780
|
-
|
|
3781
|
-
Please verify your email:
|
|
3782
|
-
https://brj.app/api/v1/customer/register-account?apiKey=PRODdh003eNKaec7PoO1AzU244tsL4WO
|
|
3783
|
-
|
|
3784
|
-
After verification, you will receive 500 000 credits for free 🎉
|
|
3785
|
-
`)));
|
|
4054
|
+
});
|
|
3786
4055
|
return process.exit(0);
|
|
3787
4056
|
}));
|
|
3788
4057
|
}
|
|
3789
4058
|
/**
|
|
3790
|
-
* TODO: Pass remote server URL (and path)
|
|
3791
4059
|
* TODO: Implement non-interactive login
|
|
3792
4060
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
3793
4061
|
* Note: [🟡] Code in this file should never be published outside of `@promptbook/cli`
|
|
@@ -4208,6 +4476,9 @@
|
|
|
4208
4476
|
/**
|
|
4209
4477
|
* Function isValidJsonString will tell you if the string is valid JSON or not
|
|
4210
4478
|
*
|
|
4479
|
+
* @param value The string to check
|
|
4480
|
+
* @returns True if the string is a valid JSON string, false otherwise
|
|
4481
|
+
*
|
|
4211
4482
|
* @public exported from `@promptbook/utils`
|
|
4212
4483
|
*/
|
|
4213
4484
|
function isValidJsonString(value /* <- [👨⚖️] */) {
|
|
@@ -4216,9 +4487,7 @@
|
|
|
4216
4487
|
return true;
|
|
4217
4488
|
}
|
|
4218
4489
|
catch (error) {
|
|
4219
|
-
|
|
4220
|
-
throw error;
|
|
4221
|
-
}
|
|
4490
|
+
assertsError(error);
|
|
4222
4491
|
if (error.message.includes('Unexpected token')) {
|
|
4223
4492
|
return false;
|
|
4224
4493
|
}
|
|
@@ -4749,8 +5018,8 @@
|
|
|
4749
5018
|
updatedAt = new Date();
|
|
4750
5019
|
errors.push(...executionResult.errors);
|
|
4751
5020
|
warnings.push(...executionResult.warnings);
|
|
4752
|
-
// <- TODO:
|
|
4753
|
-
// TODO: [🧠]
|
|
5021
|
+
// <- TODO: [🌂] Only unique errors and warnings should be added (or filtered)
|
|
5022
|
+
// TODO: [🧠] !! errors, warning, isSuccessful are redundant both in `ExecutionTask` and `ExecutionTask.currentValue`
|
|
4754
5023
|
// Also maybe move `ExecutionTask.currentValue.usage` -> `ExecutionTask.usage`
|
|
4755
5024
|
// And delete `ExecutionTask.currentValue.preparedPipeline`
|
|
4756
5025
|
assertsTaskSuccessful(executionResult);
|
|
@@ -4760,6 +5029,7 @@
|
|
|
4760
5029
|
partialResultSubject.next(executionResult);
|
|
4761
5030
|
}
|
|
4762
5031
|
catch (error) {
|
|
5032
|
+
assertsError(error);
|
|
4763
5033
|
status = 'ERROR';
|
|
4764
5034
|
errors.push(error);
|
|
4765
5035
|
partialResultSubject.error(error);
|
|
@@ -4905,13 +5175,19 @@
|
|
|
4905
5175
|
return value.toISOString();
|
|
4906
5176
|
}
|
|
4907
5177
|
else {
|
|
4908
|
-
|
|
5178
|
+
try {
|
|
5179
|
+
return JSON.stringify(value);
|
|
5180
|
+
}
|
|
5181
|
+
catch (error) {
|
|
5182
|
+
if (error instanceof TypeError && error.message.includes('circular structure')) {
|
|
5183
|
+
return VALUE_STRINGS.circular;
|
|
5184
|
+
}
|
|
5185
|
+
throw error;
|
|
5186
|
+
}
|
|
4909
5187
|
}
|
|
4910
5188
|
}
|
|
4911
5189
|
catch (error) {
|
|
4912
|
-
|
|
4913
|
-
throw error;
|
|
4914
|
-
}
|
|
5190
|
+
assertsError(error);
|
|
4915
5191
|
console.error(error);
|
|
4916
5192
|
return VALUE_STRINGS.unserializable;
|
|
4917
5193
|
}
|
|
@@ -4968,9 +5244,7 @@
|
|
|
4968
5244
|
}
|
|
4969
5245
|
}
|
|
4970
5246
|
catch (error) {
|
|
4971
|
-
|
|
4972
|
-
throw error;
|
|
4973
|
-
}
|
|
5247
|
+
assertsError(error);
|
|
4974
5248
|
throw new ParseError(spaceTrim.spaceTrim((block) => `
|
|
4975
5249
|
Can not extract variables from the script
|
|
4976
5250
|
${block(error.stack || error.message)}
|
|
@@ -5089,6 +5363,28 @@
|
|
|
5089
5363
|
// encoding: 'utf-8',
|
|
5090
5364
|
});
|
|
5091
5365
|
|
|
5366
|
+
/**
|
|
5367
|
+
* Function to check if a string is valid CSV
|
|
5368
|
+
*
|
|
5369
|
+
* @param value The string to check
|
|
5370
|
+
* @returns True if the string is a valid CSV string, false otherwise
|
|
5371
|
+
*
|
|
5372
|
+
* @public exported from `@promptbook/utils`
|
|
5373
|
+
*/
|
|
5374
|
+
function isValidCsvString(value) {
|
|
5375
|
+
try {
|
|
5376
|
+
// A simple check for CSV format: at least one comma and no invalid characters
|
|
5377
|
+
if (value.includes(',') && /^[\w\s,"']+$/.test(value)) {
|
|
5378
|
+
return true;
|
|
5379
|
+
}
|
|
5380
|
+
return false;
|
|
5381
|
+
}
|
|
5382
|
+
catch (error) {
|
|
5383
|
+
assertsError(error);
|
|
5384
|
+
return false;
|
|
5385
|
+
}
|
|
5386
|
+
}
|
|
5387
|
+
|
|
5092
5388
|
/**
|
|
5093
5389
|
* Definition for CSV spreadsheet
|
|
5094
5390
|
*
|
|
@@ -5099,7 +5395,7 @@
|
|
|
5099
5395
|
formatName: 'CSV',
|
|
5100
5396
|
aliases: ['SPREADSHEET', 'TABLE'],
|
|
5101
5397
|
isValid(value, settings, schema) {
|
|
5102
|
-
return
|
|
5398
|
+
return isValidCsvString(value);
|
|
5103
5399
|
},
|
|
5104
5400
|
canBeValid(partialValue, settings, schema) {
|
|
5105
5401
|
return true;
|
|
@@ -5253,6 +5549,30 @@
|
|
|
5253
5549
|
* TODO: [🏢] Allow to expect something inside each item of list and other formats
|
|
5254
5550
|
*/
|
|
5255
5551
|
|
|
5552
|
+
/**
|
|
5553
|
+
* Function to check if a string is valid XML
|
|
5554
|
+
*
|
|
5555
|
+
* @param value
|
|
5556
|
+
* @returns True if the string is a valid XML string, false otherwise
|
|
5557
|
+
*
|
|
5558
|
+
* @public exported from `@promptbook/utils`
|
|
5559
|
+
*/
|
|
5560
|
+
function isValidXmlString(value) {
|
|
5561
|
+
try {
|
|
5562
|
+
const parser = new DOMParser();
|
|
5563
|
+
const parsedDocument = parser.parseFromString(value, 'application/xml');
|
|
5564
|
+
const parserError = parsedDocument.getElementsByTagName('parsererror');
|
|
5565
|
+
if (parserError.length > 0) {
|
|
5566
|
+
return false;
|
|
5567
|
+
}
|
|
5568
|
+
return true;
|
|
5569
|
+
}
|
|
5570
|
+
catch (error) {
|
|
5571
|
+
assertsError(error);
|
|
5572
|
+
return false;
|
|
5573
|
+
}
|
|
5574
|
+
}
|
|
5575
|
+
|
|
5256
5576
|
/**
|
|
5257
5577
|
* Definition for XML format
|
|
5258
5578
|
*
|
|
@@ -5262,7 +5582,7 @@
|
|
|
5262
5582
|
formatName: 'XML',
|
|
5263
5583
|
mimeType: 'application/xml',
|
|
5264
5584
|
isValid(value, settings, schema) {
|
|
5265
|
-
return
|
|
5585
|
+
return isValidXmlString(value);
|
|
5266
5586
|
},
|
|
5267
5587
|
canBeValid(partialValue, settings, schema) {
|
|
5268
5588
|
return true;
|
|
@@ -5854,9 +6174,7 @@
|
|
|
5854
6174
|
break scripts;
|
|
5855
6175
|
}
|
|
5856
6176
|
catch (error) {
|
|
5857
|
-
|
|
5858
|
-
throw error;
|
|
5859
|
-
}
|
|
6177
|
+
assertsError(error);
|
|
5860
6178
|
if (error instanceof UnexpectedError) {
|
|
5861
6179
|
throw error;
|
|
5862
6180
|
}
|
|
@@ -5926,9 +6244,7 @@
|
|
|
5926
6244
|
break scripts;
|
|
5927
6245
|
}
|
|
5928
6246
|
catch (error) {
|
|
5929
|
-
|
|
5930
|
-
throw error;
|
|
5931
|
-
}
|
|
6247
|
+
assertsError(error);
|
|
5932
6248
|
if (error instanceof UnexpectedError) {
|
|
5933
6249
|
throw error;
|
|
5934
6250
|
}
|
|
@@ -6549,9 +6865,7 @@
|
|
|
6549
6865
|
await Promise.all(resolving);
|
|
6550
6866
|
}
|
|
6551
6867
|
catch (error /* <- Note: [3] */) {
|
|
6552
|
-
|
|
6553
|
-
throw error;
|
|
6554
|
-
}
|
|
6868
|
+
assertsError(error);
|
|
6555
6869
|
// Note: No need to rethrow UnexpectedError
|
|
6556
6870
|
// if (error instanceof UnexpectedError) {
|
|
6557
6871
|
// Note: Count usage, [🧠] Maybe put to separate function executionReportJsonToUsage + DRY [🤹♂️]
|
|
@@ -6817,32 +7131,6 @@
|
|
|
6817
7131
|
return mimeTypes.extension(value) || null;
|
|
6818
7132
|
}
|
|
6819
7133
|
|
|
6820
|
-
/**
|
|
6821
|
-
* The built-in `fetch' function with a lightweight error handling wrapper as default fetch function used in Promptbook scrapers
|
|
6822
|
-
*
|
|
6823
|
-
* @private as default `fetch` function used in Promptbook scrapers
|
|
6824
|
-
*/
|
|
6825
|
-
const scraperFetch = async (url, init) => {
|
|
6826
|
-
try {
|
|
6827
|
-
return await fetch(url, init);
|
|
6828
|
-
}
|
|
6829
|
-
catch (error) {
|
|
6830
|
-
if (!(error instanceof Error)) {
|
|
6831
|
-
throw error;
|
|
6832
|
-
}
|
|
6833
|
-
throw new KnowledgeScrapeError(spaceTrim__default["default"]((block) => `
|
|
6834
|
-
Can not fetch "${url}"
|
|
6835
|
-
|
|
6836
|
-
Fetch error:
|
|
6837
|
-
${block(error.message)}
|
|
6838
|
-
|
|
6839
|
-
`));
|
|
6840
|
-
}
|
|
6841
|
-
};
|
|
6842
|
-
/**
|
|
6843
|
-
* TODO: [🧠] Maybe rename because it is not used only for scrapers but also in `$getCompiledBook`
|
|
6844
|
-
*/
|
|
6845
|
-
|
|
6846
7134
|
/**
|
|
6847
7135
|
* @@@
|
|
6848
7136
|
*
|
|
@@ -6851,7 +7139,7 @@
|
|
|
6851
7139
|
async function makeKnowledgeSourceHandler(knowledgeSource, tools, options) {
|
|
6852
7140
|
// console.log('!! makeKnowledgeSourceHandler', knowledgeSource);
|
|
6853
7141
|
var _a;
|
|
6854
|
-
const { fetch =
|
|
7142
|
+
const { fetch = promptbookFetch } = tools;
|
|
6855
7143
|
const { knowledgeSourceContent } = knowledgeSource;
|
|
6856
7144
|
let { name } = knowledgeSource;
|
|
6857
7145
|
const { rootDirname = null,
|
|
@@ -7053,9 +7341,7 @@
|
|
|
7053
7341
|
knowledgePreparedUnflatten[index] = pieces;
|
|
7054
7342
|
}
|
|
7055
7343
|
catch (error) {
|
|
7056
|
-
|
|
7057
|
-
throw error;
|
|
7058
|
-
}
|
|
7344
|
+
assertsError(error);
|
|
7059
7345
|
console.warn(error);
|
|
7060
7346
|
// <- TODO: [🏮] Some standard way how to transform errors into warnings and how to handle non-critical fails during the tasks
|
|
7061
7347
|
}
|
|
@@ -7853,6 +8139,8 @@
|
|
|
7853
8139
|
*/
|
|
7854
8140
|
|
|
7855
8141
|
/**
|
|
8142
|
+
import { WrappedError } from '../../errors/WrappedError';
|
|
8143
|
+
import { assertsError } from '../../errors/assertsError';
|
|
7856
8144
|
* Parses the expect command
|
|
7857
8145
|
*
|
|
7858
8146
|
* @see `documentationUrl` for more details
|
|
@@ -7944,9 +8232,7 @@
|
|
|
7944
8232
|
};
|
|
7945
8233
|
}
|
|
7946
8234
|
catch (error) {
|
|
7947
|
-
|
|
7948
|
-
throw error;
|
|
7949
|
-
}
|
|
8235
|
+
assertsError(error);
|
|
7950
8236
|
throw new ParseError(spaceTrim__default["default"]((block) => `
|
|
7951
8237
|
Invalid FORMAT command
|
|
7952
8238
|
${block(error.message)}:
|
|
@@ -11194,9 +11480,7 @@
|
|
|
11194
11480
|
}
|
|
11195
11481
|
}
|
|
11196
11482
|
catch (error) {
|
|
11197
|
-
|
|
11198
|
-
throw error;
|
|
11199
|
-
}
|
|
11483
|
+
assertsError(error);
|
|
11200
11484
|
if (error instanceof ReferenceError) {
|
|
11201
11485
|
const undefinedName = error.message.split(' ')[0];
|
|
11202
11486
|
/*
|
|
@@ -11471,9 +11755,7 @@
|
|
|
11471
11755
|
// ---
|
|
11472
11756
|
}
|
|
11473
11757
|
catch (error) {
|
|
11474
|
-
|
|
11475
|
-
throw error;
|
|
11476
|
-
}
|
|
11758
|
+
assertsError(error);
|
|
11477
11759
|
// TODO: [7] DRY
|
|
11478
11760
|
const wrappedErrorMessage = spaceTrim__default["default"]((block) => `
|
|
11479
11761
|
${error.name} in pipeline ${fileName.split('\\').join('/')}:
|
|
@@ -11564,9 +11846,7 @@
|
|
|
11564
11846
|
}
|
|
11565
11847
|
}
|
|
11566
11848
|
catch (error) {
|
|
11567
|
-
|
|
11568
|
-
throw error;
|
|
11569
|
-
}
|
|
11849
|
+
assertsError(error);
|
|
11570
11850
|
// TODO: [7] DRY
|
|
11571
11851
|
const wrappedErrorMessage = spaceTrim__default["default"]((block) => `
|
|
11572
11852
|
${error.name} in pipeline ${fileName.split('\\').join('/')}:
|
|
@@ -11782,7 +12062,7 @@
|
|
|
11782
12062
|
isCacheReloaded,
|
|
11783
12063
|
}; /* <- TODO: ` satisfies PrepareAndScrapeOptions` */
|
|
11784
12064
|
const fs = $provideFilesystemForNode(prepareAndScrapeOptions);
|
|
11785
|
-
const llm = await $provideLlmToolsForCli({
|
|
12065
|
+
const { llm } = await $provideLlmToolsForCli({
|
|
11786
12066
|
cliOptions,
|
|
11787
12067
|
...prepareAndScrapeOptions,
|
|
11788
12068
|
});
|
|
@@ -12075,9 +12355,7 @@
|
|
|
12075
12355
|
}
|
|
12076
12356
|
}
|
|
12077
12357
|
catch (error) {
|
|
12078
|
-
|
|
12079
|
-
throw error;
|
|
12080
|
-
}
|
|
12358
|
+
assertsError(error);
|
|
12081
12359
|
console.info(colors__default["default"].red(`Prettify ${error.name} ${filename}`));
|
|
12082
12360
|
console.error(colors__default["default"].bgRed(`${error.name} in ${path.basename(__filename)}`));
|
|
12083
12361
|
console.error(colors__default["default"].red(error.stack || error.message));
|
|
@@ -12397,9 +12675,7 @@
|
|
|
12397
12675
|
return true;
|
|
12398
12676
|
}
|
|
12399
12677
|
catch (error) {
|
|
12400
|
-
|
|
12401
|
-
throw error;
|
|
12402
|
-
}
|
|
12678
|
+
assertsError(error);
|
|
12403
12679
|
return false;
|
|
12404
12680
|
}
|
|
12405
12681
|
}
|
|
@@ -12624,9 +12900,7 @@
|
|
|
12624
12900
|
ongoingParameters = result.outputParameters;
|
|
12625
12901
|
}
|
|
12626
12902
|
catch (error) {
|
|
12627
|
-
|
|
12628
|
-
throw error;
|
|
12629
|
-
}
|
|
12903
|
+
assertsError(error);
|
|
12630
12904
|
// TODO: Allow to ressurect the chatbot after an error - prompt the user to continue
|
|
12631
12905
|
console.error(colors__default["default"].red(error.stack || error.message));
|
|
12632
12906
|
return process.exit(1);
|
|
@@ -12659,7 +12933,6 @@
|
|
|
12659
12933
|
runCommand.option('-j, --json <json>', `Pass all or some input parameters as JSON record, if used the output is also returned as JSON`);
|
|
12660
12934
|
runCommand.option('-s, --save-report <path>', `Save report to file`);
|
|
12661
12935
|
runCommand.action(handleActionErrors(async (pipelineSource, cliOptions) => {
|
|
12662
|
-
console.log('!!!', cliOptions);
|
|
12663
12936
|
const { reload: isCacheReloaded, interactive: isInteractive, formfactor: isFormfactorUsed, json, verbose: isVerbose, saveReport, } = cliOptions;
|
|
12664
12937
|
if (pipelineSource.includes('-') && normalizeToKebabCase(pipelineSource) === pipelineSource) {
|
|
12665
12938
|
console.error(colors__default["default"].red(`""${pipelineSource}" is not a valid command or book. See 'ptbk --help'.`));
|
|
@@ -12685,12 +12958,10 @@
|
|
|
12685
12958
|
const fs = $provideFilesystemForNode(prepareAndScrapeOptions);
|
|
12686
12959
|
let llm;
|
|
12687
12960
|
try {
|
|
12688
|
-
llm = await $provideLlmToolsForCli({ cliOptions, ...prepareAndScrapeOptions });
|
|
12961
|
+
llm = (await $provideLlmToolsForCli({ cliOptions, ...prepareAndScrapeOptions })).llm;
|
|
12689
12962
|
}
|
|
12690
12963
|
catch (error) {
|
|
12691
|
-
|
|
12692
|
-
throw error;
|
|
12693
|
-
}
|
|
12964
|
+
assertsError(error);
|
|
12694
12965
|
if (!error.message.includes('No LLM tools')) {
|
|
12695
12966
|
throw error;
|
|
12696
12967
|
}
|
|
@@ -12740,7 +13011,7 @@
|
|
|
12740
13011
|
const tools = {
|
|
12741
13012
|
llm,
|
|
12742
13013
|
fs,
|
|
12743
|
-
fetch:
|
|
13014
|
+
fetch: promptbookFetch,
|
|
12744
13015
|
scrapers: await $provideScrapersForNode({ fs, llm, executables }, prepareAndScrapeOptions),
|
|
12745
13016
|
script: [new JavascriptExecutionTools(cliOptions)],
|
|
12746
13017
|
};
|
|
@@ -12896,6 +13167,198 @@
|
|
|
12896
13167
|
* TODO: [🖇] What about symlinks? Maybe flag --follow-symlinks
|
|
12897
13168
|
*/
|
|
12898
13169
|
|
|
13170
|
+
// TODO: !!!! List running services from REMOTE_SERVER_URLS
|
|
13171
|
+
// TODO: !!!! Import directly from YML
|
|
13172
|
+
/**
|
|
13173
|
+
* @private !!!! Decide how to expose this
|
|
13174
|
+
*/
|
|
13175
|
+
const openapiJson = {
|
|
13176
|
+
openapi: '3.0.0',
|
|
13177
|
+
info: {
|
|
13178
|
+
title: 'Promptbook Remote Server API (!!!! From TS)',
|
|
13179
|
+
version: '1.0.0',
|
|
13180
|
+
description: 'API documentation for the Promptbook Remote Server',
|
|
13181
|
+
},
|
|
13182
|
+
paths: {
|
|
13183
|
+
'/': {
|
|
13184
|
+
get: {
|
|
13185
|
+
summary: 'Get server details',
|
|
13186
|
+
description: 'Returns details about the Promptbook server.',
|
|
13187
|
+
responses: {
|
|
13188
|
+
'200': {
|
|
13189
|
+
description: 'Server details in markdown format.',
|
|
13190
|
+
},
|
|
13191
|
+
},
|
|
13192
|
+
},
|
|
13193
|
+
},
|
|
13194
|
+
'/login': {
|
|
13195
|
+
post: {
|
|
13196
|
+
summary: 'Login to the server',
|
|
13197
|
+
description: 'Login to the server and get identification.',
|
|
13198
|
+
requestBody: {
|
|
13199
|
+
required: true,
|
|
13200
|
+
content: {
|
|
13201
|
+
'application/json': {
|
|
13202
|
+
schema: {
|
|
13203
|
+
type: 'object',
|
|
13204
|
+
properties: {
|
|
13205
|
+
username: {
|
|
13206
|
+
type: 'string',
|
|
13207
|
+
},
|
|
13208
|
+
password: {
|
|
13209
|
+
type: 'string',
|
|
13210
|
+
},
|
|
13211
|
+
appId: {
|
|
13212
|
+
type: 'string',
|
|
13213
|
+
},
|
|
13214
|
+
},
|
|
13215
|
+
},
|
|
13216
|
+
},
|
|
13217
|
+
},
|
|
13218
|
+
},
|
|
13219
|
+
responses: {
|
|
13220
|
+
'200': {
|
|
13221
|
+
description: 'Successful login',
|
|
13222
|
+
content: {
|
|
13223
|
+
'application/json': {
|
|
13224
|
+
schema: {
|
|
13225
|
+
type: 'object',
|
|
13226
|
+
properties: {
|
|
13227
|
+
identification: {
|
|
13228
|
+
type: 'object',
|
|
13229
|
+
},
|
|
13230
|
+
},
|
|
13231
|
+
},
|
|
13232
|
+
},
|
|
13233
|
+
},
|
|
13234
|
+
},
|
|
13235
|
+
},
|
|
13236
|
+
},
|
|
13237
|
+
},
|
|
13238
|
+
'/books': {
|
|
13239
|
+
get: {
|
|
13240
|
+
summary: 'List all books',
|
|
13241
|
+
description: 'Returns a list of all available books in the collection.',
|
|
13242
|
+
responses: {
|
|
13243
|
+
'200': {
|
|
13244
|
+
description: 'A list of books.',
|
|
13245
|
+
content: {
|
|
13246
|
+
'application/json': {
|
|
13247
|
+
schema: {
|
|
13248
|
+
type: 'array',
|
|
13249
|
+
items: {
|
|
13250
|
+
type: 'string',
|
|
13251
|
+
},
|
|
13252
|
+
},
|
|
13253
|
+
},
|
|
13254
|
+
},
|
|
13255
|
+
},
|
|
13256
|
+
},
|
|
13257
|
+
},
|
|
13258
|
+
},
|
|
13259
|
+
'/books/{bookId}': {
|
|
13260
|
+
get: {
|
|
13261
|
+
summary: 'Get book content',
|
|
13262
|
+
description: 'Returns the content of a specific book.',
|
|
13263
|
+
parameters: [
|
|
13264
|
+
{
|
|
13265
|
+
in: 'path',
|
|
13266
|
+
name: 'bookId',
|
|
13267
|
+
required: true,
|
|
13268
|
+
schema: {
|
|
13269
|
+
type: 'string',
|
|
13270
|
+
},
|
|
13271
|
+
description: 'The ID of the book to retrieve.',
|
|
13272
|
+
},
|
|
13273
|
+
],
|
|
13274
|
+
responses: {
|
|
13275
|
+
'200': {
|
|
13276
|
+
description: 'The content of the book.',
|
|
13277
|
+
content: {
|
|
13278
|
+
'text/markdown': {
|
|
13279
|
+
schema: {
|
|
13280
|
+
type: 'string',
|
|
13281
|
+
},
|
|
13282
|
+
},
|
|
13283
|
+
},
|
|
13284
|
+
},
|
|
13285
|
+
'404': {
|
|
13286
|
+
description: 'Book not found.',
|
|
13287
|
+
},
|
|
13288
|
+
},
|
|
13289
|
+
},
|
|
13290
|
+
},
|
|
13291
|
+
'/executions': {
|
|
13292
|
+
get: {
|
|
13293
|
+
summary: 'List all executions',
|
|
13294
|
+
description: 'Returns a list of all running execution tasks.',
|
|
13295
|
+
responses: {
|
|
13296
|
+
'200': {
|
|
13297
|
+
description: 'A list of execution tasks.',
|
|
13298
|
+
content: {
|
|
13299
|
+
'application/json': {
|
|
13300
|
+
schema: {
|
|
13301
|
+
type: 'array',
|
|
13302
|
+
items: {
|
|
13303
|
+
type: 'object',
|
|
13304
|
+
},
|
|
13305
|
+
},
|
|
13306
|
+
},
|
|
13307
|
+
},
|
|
13308
|
+
},
|
|
13309
|
+
},
|
|
13310
|
+
},
|
|
13311
|
+
},
|
|
13312
|
+
'/executions/new': {
|
|
13313
|
+
post: {
|
|
13314
|
+
summary: 'Start a new execution',
|
|
13315
|
+
description: 'Starts a new execution task for a given pipeline.',
|
|
13316
|
+
requestBody: {
|
|
13317
|
+
required: true,
|
|
13318
|
+
content: {
|
|
13319
|
+
'application/json': {
|
|
13320
|
+
schema: {
|
|
13321
|
+
type: 'object',
|
|
13322
|
+
properties: {
|
|
13323
|
+
pipelineUrl: {
|
|
13324
|
+
type: 'string',
|
|
13325
|
+
},
|
|
13326
|
+
inputParameters: {
|
|
13327
|
+
type: 'object',
|
|
13328
|
+
},
|
|
13329
|
+
identification: {
|
|
13330
|
+
type: 'object',
|
|
13331
|
+
},
|
|
13332
|
+
},
|
|
13333
|
+
},
|
|
13334
|
+
},
|
|
13335
|
+
},
|
|
13336
|
+
},
|
|
13337
|
+
responses: {
|
|
13338
|
+
'200': {
|
|
13339
|
+
description: 'The newly created execution task.',
|
|
13340
|
+
content: {
|
|
13341
|
+
'application/json': {
|
|
13342
|
+
schema: {
|
|
13343
|
+
type: 'object',
|
|
13344
|
+
},
|
|
13345
|
+
},
|
|
13346
|
+
},
|
|
13347
|
+
},
|
|
13348
|
+
'400': {
|
|
13349
|
+
description: 'Invalid input.',
|
|
13350
|
+
},
|
|
13351
|
+
},
|
|
13352
|
+
},
|
|
13353
|
+
},
|
|
13354
|
+
},
|
|
13355
|
+
components: {},
|
|
13356
|
+
tags: [],
|
|
13357
|
+
};
|
|
13358
|
+
/**
|
|
13359
|
+
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
13360
|
+
*/
|
|
13361
|
+
|
|
12899
13362
|
/**
|
|
12900
13363
|
* Remote server is a proxy server that uses its execution tools internally and exposes the executor interface externally.
|
|
12901
13364
|
*
|
|
@@ -12906,7 +13369,7 @@
|
|
|
12906
13369
|
* @public exported from `@promptbook/remote-server`
|
|
12907
13370
|
*/
|
|
12908
13371
|
function startRemoteServer(options) {
|
|
12909
|
-
const { port, collection, createLlmExecutionTools, isAnonymousModeAllowed, isApplicationModeAllowed, isVerbose = DEFAULT_IS_VERBOSE, login, } = {
|
|
13372
|
+
const { port, collection, createLlmExecutionTools, createExecutionTools, isAnonymousModeAllowed, isApplicationModeAllowed, isVerbose = DEFAULT_IS_VERBOSE, login, } = {
|
|
12910
13373
|
isAnonymousModeAllowed: false,
|
|
12911
13374
|
isApplicationModeAllowed: false,
|
|
12912
13375
|
collection: null,
|
|
@@ -12914,22 +13377,6 @@
|
|
|
12914
13377
|
login: null,
|
|
12915
13378
|
...options,
|
|
12916
13379
|
};
|
|
12917
|
-
// <- TODO: [🦪] Some helper type to be able to use discriminant union types with destructuring
|
|
12918
|
-
let { rootPath = '/' } = options;
|
|
12919
|
-
if (!rootPath.startsWith('/')) {
|
|
12920
|
-
rootPath = `/${rootPath}`;
|
|
12921
|
-
} /* not else */
|
|
12922
|
-
if (rootPath.endsWith('/')) {
|
|
12923
|
-
rootPath = rootPath.slice(0, -1);
|
|
12924
|
-
} /* not else */
|
|
12925
|
-
if (rootPath === '/') {
|
|
12926
|
-
rootPath = '';
|
|
12927
|
-
}
|
|
12928
|
-
const socketioPath = '/' +
|
|
12929
|
-
`${rootPath}/socket.io`
|
|
12930
|
-
.split('/')
|
|
12931
|
-
.filter((part) => part !== '')
|
|
12932
|
-
.join('/');
|
|
12933
13380
|
const startupDate = new Date();
|
|
12934
13381
|
async function getExecutionToolsFromIdentification(identification) {
|
|
12935
13382
|
if (identification === null || identification === undefined) {
|
|
@@ -12952,23 +13399,25 @@
|
|
|
12952
13399
|
}
|
|
12953
13400
|
else if (isAnonymous === false && createLlmExecutionTools !== null) {
|
|
12954
13401
|
// Note: Application mode
|
|
12955
|
-
|
|
12956
|
-
llm = await createLlmExecutionTools({
|
|
12957
|
-
appId,
|
|
12958
|
-
userId,
|
|
12959
|
-
customOptions,
|
|
12960
|
-
});
|
|
13402
|
+
llm = await createLlmExecutionTools(identification);
|
|
12961
13403
|
}
|
|
12962
13404
|
else {
|
|
12963
13405
|
throw new PipelineExecutionError(`You must provide either llmToolsConfiguration or non-anonymous mode must be propperly configured`);
|
|
12964
13406
|
}
|
|
12965
|
-
const
|
|
12966
|
-
const
|
|
13407
|
+
const customExecutionTools = createExecutionTools ? await createExecutionTools(identification) : {};
|
|
13408
|
+
const fs = customExecutionTools.fs || $provideFilesystemForNode();
|
|
13409
|
+
const executables = customExecutionTools.executables || (await $provideExecutablesForNode());
|
|
13410
|
+
const scrapers = customExecutionTools.scrapers || (await $provideScrapersForNode({ fs, llm, executables }));
|
|
13411
|
+
const script = customExecutionTools.script || (await $provideScriptingForNode({}));
|
|
13412
|
+
const fetch = customExecutionTools.fetch || promptbookFetch;
|
|
13413
|
+
const userInterface = customExecutionTools.userInterface || undefined;
|
|
12967
13414
|
const tools = {
|
|
12968
13415
|
llm,
|
|
12969
13416
|
fs,
|
|
12970
|
-
scrapers
|
|
12971
|
-
script
|
|
13417
|
+
scrapers,
|
|
13418
|
+
script,
|
|
13419
|
+
fetch,
|
|
13420
|
+
userInterface,
|
|
12972
13421
|
};
|
|
12973
13422
|
return tools;
|
|
12974
13423
|
}
|
|
@@ -12978,39 +13427,27 @@
|
|
|
12978
13427
|
response.setHeader('X-Powered-By', 'Promptbook engine');
|
|
12979
13428
|
next();
|
|
12980
13429
|
});
|
|
12981
|
-
|
|
12982
|
-
|
|
12983
|
-
|
|
12984
|
-
|
|
12985
|
-
|
|
12986
|
-
version: '1.0.0',
|
|
12987
|
-
description: 'API documentation for the Promptbook Remote Server',
|
|
12988
|
-
},
|
|
12989
|
-
servers: [
|
|
12990
|
-
{
|
|
12991
|
-
url: `http://localhost:${port}${rootPath}`,
|
|
12992
|
-
// <- TODO: !!!!! Probbably: Pass `remoteServerUrl` instead of `port` and `rootPath`
|
|
12993
|
-
},
|
|
12994
|
-
],
|
|
13430
|
+
// TODO: !!!! Expose openapiJson to consumer and also allow to add new routes
|
|
13431
|
+
app.use(OpenApiValidator__namespace.middleware({
|
|
13432
|
+
apiSpec: openapiJson,
|
|
13433
|
+
ignorePaths(path) {
|
|
13434
|
+
return path.startsWith('/api-docs') || path.startsWith('/swagger') || path.startsWith('/openapi');
|
|
12995
13435
|
},
|
|
12996
|
-
|
|
12997
|
-
|
|
12998
|
-
|
|
12999
|
-
app.use([`/api-docs`,
|
|
13436
|
+
validateRequests: true,
|
|
13437
|
+
validateResponses: true,
|
|
13438
|
+
}));
|
|
13439
|
+
app.use([`/api-docs`, `/swagger`], swaggerUi__default["default"].serve, swaggerUi__default["default"].setup(openapiJson, {
|
|
13440
|
+
// customCss: '.swagger-ui .topbar { display: none }',
|
|
13441
|
+
// customSiteTitle: 'BRJ API',
|
|
13442
|
+
// customfavIcon: 'https://brj.app/favicon.ico',
|
|
13443
|
+
}));
|
|
13444
|
+
app.get(`/openapi`, (request, response) => {
|
|
13445
|
+
response.json(openapiJson);
|
|
13446
|
+
});
|
|
13000
13447
|
const runningExecutionTasks = [];
|
|
13001
13448
|
// <- TODO: [🤬] Identify the users
|
|
13002
13449
|
// TODO: [🧠] Do here some garbage collection of finished tasks
|
|
13003
|
-
|
|
13004
|
-
* @swagger
|
|
13005
|
-
* /:
|
|
13006
|
-
* get:
|
|
13007
|
-
* summary: Get server details
|
|
13008
|
-
* description: Returns details about the Promptbook server.
|
|
13009
|
-
* responses:
|
|
13010
|
-
* 200:
|
|
13011
|
-
* description: Server details in markdown format.
|
|
13012
|
-
*/
|
|
13013
|
-
app.get(['/', rootPath], async (request, response) => {
|
|
13450
|
+
app.get('/', async (request, response) => {
|
|
13014
13451
|
var _a;
|
|
13015
13452
|
if ((_a = request.url) === null || _a === void 0 ? void 0 : _a.includes('socket.io')) {
|
|
13016
13453
|
return;
|
|
@@ -13029,8 +13466,6 @@
|
|
|
13029
13466
|
## Details
|
|
13030
13467
|
|
|
13031
13468
|
**Server port:** ${port}
|
|
13032
|
-
**Server root path:** ${rootPath}
|
|
13033
|
-
**Socket.io path:** ${socketioPath}
|
|
13034
13469
|
**Startup date:** ${startupDate.toISOString()}
|
|
13035
13470
|
**Anonymouse mode:** ${isAnonymousModeAllowed ? 'enabled' : 'disabled'}
|
|
13036
13471
|
**Application mode:** ${isApplicationModeAllowed ? 'enabled' : 'disabled'}
|
|
@@ -13069,38 +13504,7 @@
|
|
|
13069
13504
|
https://github.com/webgptorg/promptbook
|
|
13070
13505
|
`));
|
|
13071
13506
|
});
|
|
13072
|
-
|
|
13073
|
-
* @swagger
|
|
13074
|
-
*
|
|
13075
|
-
* /login:
|
|
13076
|
-
* post:
|
|
13077
|
-
* summary: Login to the server
|
|
13078
|
-
* description: Login to the server and get identification.
|
|
13079
|
-
* requestBody:
|
|
13080
|
-
* required: true
|
|
13081
|
-
* content:
|
|
13082
|
-
* application/json:
|
|
13083
|
-
* schema:
|
|
13084
|
-
* type: object
|
|
13085
|
-
* properties:
|
|
13086
|
-
* username:
|
|
13087
|
-
* type: string
|
|
13088
|
-
* password:
|
|
13089
|
-
* type: string
|
|
13090
|
-
* appId:
|
|
13091
|
-
* type: string
|
|
13092
|
-
* responses:
|
|
13093
|
-
* 200:
|
|
13094
|
-
* description: Successful login
|
|
13095
|
-
* content:
|
|
13096
|
-
* application/json:
|
|
13097
|
-
* schema:
|
|
13098
|
-
* type: object
|
|
13099
|
-
* properties:
|
|
13100
|
-
* identification:
|
|
13101
|
-
* type: object
|
|
13102
|
-
*/
|
|
13103
|
-
app.post([`/login`, `${rootPath}/login`], async (request, response) => {
|
|
13507
|
+
app.post(`/login`, async (request, response) => {
|
|
13104
13508
|
if (!isApplicationModeAllowed || login === null) {
|
|
13105
13509
|
response.status(400).send('Application mode is not allowed');
|
|
13106
13510
|
return;
|
|
@@ -13125,9 +13529,7 @@
|
|
|
13125
13529
|
return;
|
|
13126
13530
|
}
|
|
13127
13531
|
catch (error) {
|
|
13128
|
-
|
|
13129
|
-
throw error;
|
|
13130
|
-
}
|
|
13532
|
+
assertsError(error);
|
|
13131
13533
|
if (error instanceof AuthenticationError) {
|
|
13132
13534
|
response.status(401).send({
|
|
13133
13535
|
isSuccess: false,
|
|
@@ -13142,23 +13544,7 @@
|
|
|
13142
13544
|
response.status(400).send({ error: serializeError(error) });
|
|
13143
13545
|
}
|
|
13144
13546
|
});
|
|
13145
|
-
|
|
13146
|
-
* @swagger
|
|
13147
|
-
* /books:
|
|
13148
|
-
* get:
|
|
13149
|
-
* summary: List all books
|
|
13150
|
-
* description: Returns a list of all available books in the collection.
|
|
13151
|
-
* responses:
|
|
13152
|
-
* 200:
|
|
13153
|
-
* description: A list of books.
|
|
13154
|
-
* content:
|
|
13155
|
-
* application/json:
|
|
13156
|
-
* schema:
|
|
13157
|
-
* type: array
|
|
13158
|
-
* items:
|
|
13159
|
-
* type: string
|
|
13160
|
-
*/
|
|
13161
|
-
app.get([`/books`, `${rootPath}/books`], async (request, response) => {
|
|
13547
|
+
app.get(`/books`, async (request, response) => {
|
|
13162
13548
|
if (collection === null) {
|
|
13163
13549
|
response.status(500).send('No collection available');
|
|
13164
13550
|
return;
|
|
@@ -13168,30 +13554,7 @@
|
|
|
13168
13554
|
response.send(pipelines);
|
|
13169
13555
|
});
|
|
13170
13556
|
// TODO: [🧠] Is it secure / good idea to expose source codes of hosted books
|
|
13171
|
-
|
|
13172
|
-
* @swagger
|
|
13173
|
-
* /books/{bookId}:
|
|
13174
|
-
* get:
|
|
13175
|
-
* summary: Get book content
|
|
13176
|
-
* description: Returns the content of a specific book.
|
|
13177
|
-
* parameters:
|
|
13178
|
-
* - in: path
|
|
13179
|
-
* name: bookId
|
|
13180
|
-
* required: true
|
|
13181
|
-
* schema:
|
|
13182
|
-
* type: string
|
|
13183
|
-
* description: The ID of the book to retrieve.
|
|
13184
|
-
* responses:
|
|
13185
|
-
* 200:
|
|
13186
|
-
* description: The content of the book.
|
|
13187
|
-
* content:
|
|
13188
|
-
* text/markdown:
|
|
13189
|
-
* schema:
|
|
13190
|
-
* type: string
|
|
13191
|
-
* 404:
|
|
13192
|
-
* description: Book not found.
|
|
13193
|
-
*/
|
|
13194
|
-
app.get([`/books/*`, `${rootPath}/books/*`], async (request, response) => {
|
|
13557
|
+
app.get(`/books/*`, async (request, response) => {
|
|
13195
13558
|
try {
|
|
13196
13559
|
if (collection === null) {
|
|
13197
13560
|
response.status(500).send('No collection nor books available');
|
|
@@ -13210,9 +13573,7 @@
|
|
|
13210
13573
|
.send(source.content);
|
|
13211
13574
|
}
|
|
13212
13575
|
catch (error) {
|
|
13213
|
-
|
|
13214
|
-
throw error;
|
|
13215
|
-
}
|
|
13576
|
+
assertsError(error);
|
|
13216
13577
|
response
|
|
13217
13578
|
.status(404)
|
|
13218
13579
|
.send({ error: serializeError(error) });
|
|
@@ -13245,26 +13606,10 @@
|
|
|
13245
13606
|
};
|
|
13246
13607
|
}
|
|
13247
13608
|
}
|
|
13248
|
-
|
|
13249
|
-
|
|
13250
|
-
* /executions:
|
|
13251
|
-
* get:
|
|
13252
|
-
* summary: List all executions
|
|
13253
|
-
* description: Returns a list of all running execution tasks.
|
|
13254
|
-
* responses:
|
|
13255
|
-
* 200:
|
|
13256
|
-
* description: A list of execution tasks.
|
|
13257
|
-
* content:
|
|
13258
|
-
* application/json:
|
|
13259
|
-
* schema:
|
|
13260
|
-
* type: array
|
|
13261
|
-
* items:
|
|
13262
|
-
* type: object
|
|
13263
|
-
*/
|
|
13264
|
-
app.get([`/executions`, `${rootPath}/executions`], async (request, response) => {
|
|
13265
|
-
response.send(runningExecutionTasks.map((runningExecutionTask) => exportExecutionTask(runningExecutionTask, false)));
|
|
13609
|
+
app.get(`/executions`, async (request, response) => {
|
|
13610
|
+
response.send(runningExecutionTasks.map((runningExecutionTask) => exportExecutionTask(runningExecutionTask, false)) /* <- TODO: satisfies paths['/executions']['get']['responses']['200']['content']['application/json'] */);
|
|
13266
13611
|
});
|
|
13267
|
-
app.get(
|
|
13612
|
+
app.get(`/executions/last`, async (request, response) => {
|
|
13268
13613
|
// TODO: [🤬] Filter only for user
|
|
13269
13614
|
if (runningExecutionTasks.length === 0) {
|
|
13270
13615
|
response.status(404).send('No execution tasks found');
|
|
@@ -13273,7 +13618,7 @@
|
|
|
13273
13618
|
const lastExecutionTask = runningExecutionTasks[runningExecutionTasks.length - 1];
|
|
13274
13619
|
response.send(exportExecutionTask(lastExecutionTask, true));
|
|
13275
13620
|
});
|
|
13276
|
-
app.get(
|
|
13621
|
+
app.get(`/executions/:taskId`, async (request, response) => {
|
|
13277
13622
|
const { taskId } = request.params;
|
|
13278
13623
|
// TODO: [🤬] Filter only for user
|
|
13279
13624
|
const executionTask = runningExecutionTasks.find((executionTask) => executionTask.taskId === taskId);
|
|
@@ -13285,39 +13630,12 @@
|
|
|
13285
13630
|
}
|
|
13286
13631
|
response.send(exportExecutionTask(executionTask, true));
|
|
13287
13632
|
});
|
|
13288
|
-
|
|
13289
|
-
* @swagger
|
|
13290
|
-
* /executions/new:
|
|
13291
|
-
* post:
|
|
13292
|
-
* summary: Start a new execution
|
|
13293
|
-
* description: Starts a new execution task for a given pipeline.
|
|
13294
|
-
* requestBody:
|
|
13295
|
-
* required: true
|
|
13296
|
-
* content:
|
|
13297
|
-
* application/json:
|
|
13298
|
-
* schema:
|
|
13299
|
-
* type: object
|
|
13300
|
-
* properties:
|
|
13301
|
-
* pipelineUrl:
|
|
13302
|
-
* type: string
|
|
13303
|
-
* inputParameters:
|
|
13304
|
-
* type: object
|
|
13305
|
-
* identification:
|
|
13306
|
-
* type: object
|
|
13307
|
-
* responses:
|
|
13308
|
-
* 200:
|
|
13309
|
-
* description: The newly created execution task.
|
|
13310
|
-
* content:
|
|
13311
|
-
* application/json:
|
|
13312
|
-
* schema:
|
|
13313
|
-
* type: object
|
|
13314
|
-
* 400:
|
|
13315
|
-
* description: Invalid input.
|
|
13316
|
-
*/
|
|
13317
|
-
app.post([`/executions/new`, `${rootPath}/executions/new`], async (request, response) => {
|
|
13633
|
+
app.post(`/executions/new`, async (request, response) => {
|
|
13318
13634
|
try {
|
|
13319
13635
|
const { inputParameters, identification /* <- [🤬] */ } = request.body;
|
|
13320
|
-
const pipelineUrl = request.body
|
|
13636
|
+
const pipelineUrl = request.body
|
|
13637
|
+
.pipelineUrl /* <- TODO: as paths['/executions/new']['post']['requestBody']['content']['application/json'] */ ||
|
|
13638
|
+
request.body.book;
|
|
13321
13639
|
// TODO: [🧠] Check `pipelineUrl` and `inputParameters` here or it should be responsibility of `collection.getPipelineByUrl` and `pipelineExecutor`
|
|
13322
13640
|
const pipeline = await (collection === null || collection === void 0 ? void 0 : collection.getPipelineByUrl(pipelineUrl));
|
|
13323
13641
|
if (pipeline === undefined) {
|
|
@@ -13331,7 +13649,7 @@
|
|
|
13331
13649
|
await waitasecond.forTime(10);
|
|
13332
13650
|
// <- Note: Wait for a while to wait for quick responses or sudden but asynchronous errors
|
|
13333
13651
|
// <- TODO: Put this into configuration
|
|
13334
|
-
response.send(executionTask);
|
|
13652
|
+
response.send(executionTask /* <- TODO: satisfies paths['/executions/new']['post']['responses']['200']['content']['application/json'] */);
|
|
13335
13653
|
/*/
|
|
13336
13654
|
executionTask.asObservable().subscribe({
|
|
13337
13655
|
next(partialResult) {
|
|
@@ -13351,19 +13669,24 @@
|
|
|
13351
13669
|
*/
|
|
13352
13670
|
}
|
|
13353
13671
|
catch (error) {
|
|
13354
|
-
|
|
13355
|
-
throw error;
|
|
13356
|
-
}
|
|
13672
|
+
assertsError(error);
|
|
13357
13673
|
response.status(400).send({ error: serializeError(error) });
|
|
13358
13674
|
}
|
|
13359
13675
|
});
|
|
13676
|
+
/**
|
|
13677
|
+
* Catch-all handler for unmatched routes
|
|
13678
|
+
*/
|
|
13679
|
+
app.use((request, response) => {
|
|
13680
|
+
response.status(404).send(`URL "${request.originalUrl}" was not found on Promptbook server.`);
|
|
13681
|
+
});
|
|
13360
13682
|
const httpServer = http__default["default"].createServer(app);
|
|
13361
13683
|
const server = new socket_io.Server(httpServer, {
|
|
13362
|
-
path:
|
|
13363
|
-
transports: [
|
|
13684
|
+
path: '/socket.io',
|
|
13685
|
+
transports: ['polling', 'websocket' /*, <- TODO: [🌬] Allow to pass `transports`, add 'webtransport' */],
|
|
13364
13686
|
cors: {
|
|
13365
13687
|
origin: '*',
|
|
13366
13688
|
methods: ['GET', 'POST'],
|
|
13689
|
+
// <- TODO: [🌡] Allow to pass
|
|
13367
13690
|
},
|
|
13368
13691
|
});
|
|
13369
13692
|
server.on('connection', (socket) => {
|
|
@@ -13417,9 +13740,7 @@
|
|
|
13417
13740
|
socket.emit('prompt-response', { promptResult } /* <- Note: [🤛] */);
|
|
13418
13741
|
}
|
|
13419
13742
|
catch (error) {
|
|
13420
|
-
|
|
13421
|
-
throw error;
|
|
13422
|
-
}
|
|
13743
|
+
assertsError(error);
|
|
13423
13744
|
socket.emit('error', serializeError(error) /* <- Note: [🤛] */);
|
|
13424
13745
|
}
|
|
13425
13746
|
finally {
|
|
@@ -13441,9 +13762,7 @@
|
|
|
13441
13762
|
socket.emit('listModels-response', { models } /* <- Note: [🤛] */);
|
|
13442
13763
|
}
|
|
13443
13764
|
catch (error) {
|
|
13444
|
-
|
|
13445
|
-
throw error;
|
|
13446
|
-
}
|
|
13765
|
+
assertsError(error);
|
|
13447
13766
|
socket.emit('error', serializeError(error));
|
|
13448
13767
|
}
|
|
13449
13768
|
finally {
|
|
@@ -13464,9 +13783,7 @@
|
|
|
13464
13783
|
socket.emit('preparePipeline-response', { preparedPipeline } /* <- Note: [🤛] */);
|
|
13465
13784
|
}
|
|
13466
13785
|
catch (error) {
|
|
13467
|
-
|
|
13468
|
-
throw error;
|
|
13469
|
-
}
|
|
13786
|
+
assertsError(error);
|
|
13470
13787
|
socket.emit('error', serializeError(error));
|
|
13471
13788
|
// <- TODO: [🚋] There is a problem with the remote server handling errors and sending them back to the client
|
|
13472
13789
|
}
|
|
@@ -13514,8 +13831,7 @@
|
|
|
13514
13831
|
};
|
|
13515
13832
|
}
|
|
13516
13833
|
/**
|
|
13517
|
-
* TODO:
|
|
13518
|
-
* TODO: [👩🏾🤝🧑🏾] Allow to pass custom fetch function here - PromptbookFetch
|
|
13834
|
+
* TODO: [🌡] Add CORS and security - probbably via `helmet`
|
|
13519
13835
|
* TODO: Split this file into multiple functions - handler for each request
|
|
13520
13836
|
* TODO: Maybe use `$exportJson`
|
|
13521
13837
|
* TODO: [🧠][🛍] Maybe not `isAnonymous: boolean` BUT `mode: 'ANONYMOUS'|'COLLECTION'`
|
|
@@ -13574,9 +13890,9 @@
|
|
|
13574
13890
|
if (url !== null) {
|
|
13575
13891
|
rootUrl = suffixUrl(url, '/books');
|
|
13576
13892
|
}
|
|
13577
|
-
|
|
13578
|
-
|
|
13579
|
-
|
|
13893
|
+
if (url !== null && url.pathname !== '/' && url.pathname !== '') {
|
|
13894
|
+
console.error(colors__default["default"].red(`URL of the server can not have path, but got "${url.pathname}"`));
|
|
13895
|
+
process.exit(1);
|
|
13580
13896
|
}
|
|
13581
13897
|
// TODO: DRY [◽]
|
|
13582
13898
|
const prepareAndScrapeOptions = {
|
|
@@ -13584,7 +13900,7 @@
|
|
|
13584
13900
|
isCacheReloaded,
|
|
13585
13901
|
}; /* <- TODO: ` satisfies PrepareAndScrapeOptions` */
|
|
13586
13902
|
const fs = $provideFilesystemForNode(prepareAndScrapeOptions);
|
|
13587
|
-
const llm = await $provideLlmToolsForCli({ cliOptions, ...prepareAndScrapeOptions });
|
|
13903
|
+
const { /* [0] strategy,*/ llm } = await $provideLlmToolsForCli({ cliOptions, ...prepareAndScrapeOptions });
|
|
13588
13904
|
const executables = await $provideExecutablesForNode(prepareAndScrapeOptions);
|
|
13589
13905
|
const tools = {
|
|
13590
13906
|
llm,
|
|
@@ -13603,7 +13919,6 @@
|
|
|
13603
13919
|
});
|
|
13604
13920
|
// console.log(path, await collection.listPipelines());
|
|
13605
13921
|
const server = startRemoteServer({
|
|
13606
|
-
rootPath,
|
|
13607
13922
|
port,
|
|
13608
13923
|
isAnonymousModeAllowed,
|
|
13609
13924
|
isApplicationModeAllowed: true,
|
|
@@ -13616,6 +13931,7 @@
|
|
|
13616
13931
|
TODO_USE({ appId, userId });
|
|
13617
13932
|
return llm;
|
|
13618
13933
|
},
|
|
13934
|
+
// <- TODO: [🧠][0] Maybe pass here strategy
|
|
13619
13935
|
});
|
|
13620
13936
|
keepUnused(server);
|
|
13621
13937
|
// Note: Already logged by `startRemoteServer`
|
|
@@ -13657,7 +13973,7 @@
|
|
|
13657
13973
|
isCacheReloaded,
|
|
13658
13974
|
}; /* <- TODO: ` satisfies PrepareAndScrapeOptions` */
|
|
13659
13975
|
const fs = $provideFilesystemForNode(prepareAndScrapeOptions);
|
|
13660
|
-
const llm = await $provideLlmToolsForCli({ cliOptions, ...prepareAndScrapeOptions });
|
|
13976
|
+
const { llm } = await $provideLlmToolsForCli({ cliOptions, ...prepareAndScrapeOptions });
|
|
13661
13977
|
const executables = await $provideExecutablesForNode(prepareAndScrapeOptions);
|
|
13662
13978
|
tools = {
|
|
13663
13979
|
llm,
|
|
@@ -13696,9 +14012,7 @@
|
|
|
13696
14012
|
}
|
|
13697
14013
|
}
|
|
13698
14014
|
catch (error) {
|
|
13699
|
-
|
|
13700
|
-
throw error;
|
|
13701
|
-
}
|
|
14015
|
+
assertsError(error);
|
|
13702
14016
|
console.info(colors__default["default"].red(`Pipeline is not valid ${filename}`));
|
|
13703
14017
|
console.error(colors__default["default"].bgRed(`${error.name} in ${path.basename(__filename)}`));
|
|
13704
14018
|
console.error(colors__default["default"].red(error.stack || error.message));
|
|
@@ -13922,7 +14236,25 @@
|
|
|
13922
14236
|
output: computeUsage(`$2.40 / 1M tokens`),
|
|
13923
14237
|
},
|
|
13924
14238
|
},
|
|
13925
|
-
|
|
14239
|
+
{
|
|
14240
|
+
modelVariant: 'CHAT',
|
|
14241
|
+
modelTitle: 'Claude 3.7 Sonnet',
|
|
14242
|
+
modelName: 'claude-3-7-sonnet-20250219',
|
|
14243
|
+
pricing: {
|
|
14244
|
+
prompt: computeUsage(`$3.00 / 1M tokens`),
|
|
14245
|
+
output: computeUsage(`$15.00 / 1M tokens`),
|
|
14246
|
+
},
|
|
14247
|
+
},
|
|
14248
|
+
{
|
|
14249
|
+
modelVariant: 'CHAT',
|
|
14250
|
+
modelTitle: 'Claude 3.5 Haiku',
|
|
14251
|
+
modelName: 'claude-3-5-haiku-20241022',
|
|
14252
|
+
pricing: {
|
|
14253
|
+
prompt: computeUsage(`$0.25 / 1M tokens`),
|
|
14254
|
+
output: computeUsage(`$1.25 / 1M tokens`),
|
|
14255
|
+
},
|
|
14256
|
+
},
|
|
14257
|
+
// <- [🕕]
|
|
13926
14258
|
],
|
|
13927
14259
|
});
|
|
13928
14260
|
/**
|
|
@@ -14687,7 +15019,6 @@
|
|
|
14687
15019
|
prompt: computeUsage(`$5.00 / 1M tokens`),
|
|
14688
15020
|
output: computeUsage(`$15.00 / 1M tokens`),
|
|
14689
15021
|
},
|
|
14690
|
-
//TODO: [main] !!3 Add gpt-4o-mini-2024-07-18 and all others to be up to date
|
|
14691
15022
|
},
|
|
14692
15023
|
/**/
|
|
14693
15024
|
/**/
|
|
@@ -14702,6 +15033,17 @@
|
|
|
14702
15033
|
},
|
|
14703
15034
|
/**/
|
|
14704
15035
|
/**/
|
|
15036
|
+
{
|
|
15037
|
+
modelVariant: 'CHAT',
|
|
15038
|
+
modelTitle: 'gpt-4o-mini',
|
|
15039
|
+
modelName: 'gpt-4o-mini',
|
|
15040
|
+
pricing: {
|
|
15041
|
+
prompt: computeUsage(`$3.00 / 1M tokens`),
|
|
15042
|
+
output: computeUsage(`$9.00 / 1M tokens`),
|
|
15043
|
+
},
|
|
15044
|
+
},
|
|
15045
|
+
/**/
|
|
15046
|
+
/**/
|
|
14705
15047
|
{
|
|
14706
15048
|
modelVariant: 'CHAT',
|
|
14707
15049
|
modelTitle: 'o1-preview',
|
|
@@ -14781,6 +15123,7 @@
|
|
|
14781
15123
|
},
|
|
14782
15124
|
},
|
|
14783
15125
|
/**/
|
|
15126
|
+
// <- [🕕]
|
|
14784
15127
|
],
|
|
14785
15128
|
});
|
|
14786
15129
|
/**
|
|
@@ -15349,11 +15692,17 @@
|
|
|
15349
15692
|
description: 'Implementation of Deepseek models',
|
|
15350
15693
|
vercelProvider: deepseekVercelProvider,
|
|
15351
15694
|
availableModels: [
|
|
15352
|
-
|
|
15353
|
-
|
|
15354
|
-
|
|
15695
|
+
{
|
|
15696
|
+
modelName: 'deepseek-chat',
|
|
15697
|
+
modelVariant: 'CHAT',
|
|
15698
|
+
},
|
|
15699
|
+
{
|
|
15700
|
+
modelName: 'deepseek-reasoner',
|
|
15701
|
+
modelVariant: 'CHAT',
|
|
15702
|
+
},
|
|
15703
|
+
// <- [🕕]
|
|
15355
15704
|
// <- TODO: How picking of the default model looks like in `createExecutionToolsFromVercelProvider`
|
|
15356
|
-
]
|
|
15705
|
+
],
|
|
15357
15706
|
...options,
|
|
15358
15707
|
});
|
|
15359
15708
|
}, {
|
|
@@ -15451,6 +15800,10 @@
|
|
|
15451
15800
|
vercelProvider: googleGeminiVercelProvider,
|
|
15452
15801
|
availableModels: [
|
|
15453
15802
|
// TODO: [🕘] Maybe list models in same way as in other providers - in separate file with metadata
|
|
15803
|
+
'gemini-2.5-pro-preview-03-25',
|
|
15804
|
+
'gemini-2.0-flash',
|
|
15805
|
+
'gemini-2.0-flash-lite',
|
|
15806
|
+
'gemini-2.0-flash-thinking-exp-01-21',
|
|
15454
15807
|
'gemini-1.5-flash',
|
|
15455
15808
|
'gemini-1.5-flash-latest',
|
|
15456
15809
|
'gemini-1.5-flash-001',
|
|
@@ -15466,6 +15819,7 @@
|
|
|
15466
15819
|
'gemini-1.5-pro-002',
|
|
15467
15820
|
'gemini-1.5-pro-exp-0827',
|
|
15468
15821
|
'gemini-1.0-pro',
|
|
15822
|
+
// <- [🕕]
|
|
15469
15823
|
].map((modelName) => ({ modelName, modelVariant: 'CHAT' })),
|
|
15470
15824
|
...options,
|
|
15471
15825
|
});
|
|
@@ -15745,6 +16099,7 @@
|
|
|
15745
16099
|
console.info(colors__default["default"].bgWhite('rawRequest'), JSON.stringify(rawRequest, null, 4));
|
|
15746
16100
|
}
|
|
15747
16101
|
const rawResponse = await client.chat.completions.create(rawRequest).catch((error) => {
|
|
16102
|
+
assertsError(error);
|
|
15748
16103
|
if (this.options.isVerbose) {
|
|
15749
16104
|
console.info(colors__default["default"].bgRed('error'), error);
|
|
15750
16105
|
}
|
|
@@ -15821,6 +16176,7 @@
|
|
|
15821
16176
|
console.info(colors__default["default"].bgWhite('rawRequest'), JSON.stringify(rawRequest, null, 4));
|
|
15822
16177
|
}
|
|
15823
16178
|
const rawResponse = await client.completions.create(rawRequest).catch((error) => {
|
|
16179
|
+
assertsError(error);
|
|
15824
16180
|
if (this.options.isVerbose) {
|
|
15825
16181
|
console.info(colors__default["default"].bgRed('error'), error);
|
|
15826
16182
|
}
|
|
@@ -15884,6 +16240,7 @@
|
|
|
15884
16240
|
console.info(colors__default["default"].bgWhite('rawRequest'), JSON.stringify(rawRequest, null, 4));
|
|
15885
16241
|
}
|
|
15886
16242
|
const rawResponse = await client.embeddings.create(rawRequest).catch((error) => {
|
|
16243
|
+
assertsError(error);
|
|
15887
16244
|
if (this.options.isVerbose) {
|
|
15888
16245
|
console.info(colors__default["default"].bgRed('error'), error);
|
|
15889
16246
|
}
|