@promptbook/cli 0.85.0-9 → 0.85.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
CHANGED
|
@@ -24,10 +24,6 @@
|
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
|
|
27
|
-
<blockquote style="color: #ff8811">
|
|
28
|
-
<b>⚠ Warning:</b> This is a pre-release version of the library. It is not yet ready for production use. Please look at <a href="https://www.npmjs.com/package/@promptbook/core?activeTab=versions">latest stable release</a>.
|
|
29
|
-
</blockquote>
|
|
30
|
-
|
|
31
27
|
## 📦 Package `@promptbook/cli`
|
|
32
28
|
|
|
33
29
|
- Promptbooks are [divided into several](#-packages) packages, all are published from [single monorepo](https://github.com/webgptorg/promptbook).
|
package/esm/index.es.js
CHANGED
|
@@ -2,7 +2,7 @@ import colors from 'colors';
|
|
|
2
2
|
import commander from 'commander';
|
|
3
3
|
import spaceTrim, { spaceTrim as spaceTrim$1 } from 'spacetrim';
|
|
4
4
|
import { forTime, forEver } from 'waitasecond';
|
|
5
|
-
import { basename, join, dirname } from 'path';
|
|
5
|
+
import { basename, join, dirname, relative } from 'path';
|
|
6
6
|
import { stat, access, constants, readFile, writeFile, readdir, mkdir, unlink, rm, rmdir, rename } from 'fs/promises';
|
|
7
7
|
import hexEncoder from 'crypto-js/enc-hex';
|
|
8
8
|
import sha256 from 'crypto-js/sha256';
|
|
@@ -43,7 +43,7 @@ var BOOK_LANGUAGE_VERSION = '1.0.0';
|
|
|
43
43
|
* @generated
|
|
44
44
|
* @see https://github.com/webgptorg/promptbook
|
|
45
45
|
*/
|
|
46
|
-
var PROMPTBOOK_ENGINE_VERSION = '0.85.0-
|
|
46
|
+
var PROMPTBOOK_ENGINE_VERSION = '0.85.0-16';
|
|
47
47
|
/**
|
|
48
48
|
* TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
|
|
49
49
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
@@ -4059,57 +4059,6 @@ function isValidPromptbookVersion(version) {
|
|
|
4059
4059
|
return true;
|
|
4060
4060
|
}
|
|
4061
4061
|
|
|
4062
|
-
/**
|
|
4063
|
-
* Checks if an URL is reserved for private networks or localhost.
|
|
4064
|
-
*
|
|
4065
|
-
* Note: There are two simmilar functions:
|
|
4066
|
-
* - `isUrlOnPrivateNetwork` which tests full URL
|
|
4067
|
-
* - `isHostnameOnPrivateNetwork` *(this one)* which tests just hostname
|
|
4068
|
-
*
|
|
4069
|
-
* @public exported from `@promptbook/utils`
|
|
4070
|
-
*/
|
|
4071
|
-
function isHostnameOnPrivateNetwork(hostname) {
|
|
4072
|
-
if (hostname === 'example.com' ||
|
|
4073
|
-
hostname === 'localhost' ||
|
|
4074
|
-
hostname.endsWith('.localhost') ||
|
|
4075
|
-
hostname.endsWith('.local') ||
|
|
4076
|
-
hostname.endsWith('.test') ||
|
|
4077
|
-
hostname === '127.0.0.1' ||
|
|
4078
|
-
hostname === '::1') {
|
|
4079
|
-
return true;
|
|
4080
|
-
}
|
|
4081
|
-
if (hostname.includes(':')) {
|
|
4082
|
-
// IPv6
|
|
4083
|
-
var ipParts = hostname.split(':');
|
|
4084
|
-
return ipParts[0] === 'fc00' || ipParts[0] === 'fd00' || ipParts[0] === 'fe80';
|
|
4085
|
-
}
|
|
4086
|
-
else {
|
|
4087
|
-
// IPv4
|
|
4088
|
-
var ipParts = hostname.split('.').map(function (part) { return Number.parseInt(part, 10); });
|
|
4089
|
-
return (ipParts[0] === 10 ||
|
|
4090
|
-
(ipParts[0] === 172 && ipParts[1] >= 16 && ipParts[1] <= 31) ||
|
|
4091
|
-
(ipParts[0] === 192 && ipParts[1] === 168));
|
|
4092
|
-
}
|
|
4093
|
-
}
|
|
4094
|
-
|
|
4095
|
-
/**
|
|
4096
|
-
* Checks if an IP address or hostname is reserved for private networks or localhost.
|
|
4097
|
-
*
|
|
4098
|
-
* Note: There are two simmilar functions:
|
|
4099
|
-
* - `isUrlOnPrivateNetwork` *(this one)* which tests full URL
|
|
4100
|
-
* - `isHostnameOnPrivateNetwork` which tests just hostname
|
|
4101
|
-
*
|
|
4102
|
-
* @param {string} ipAddress - The IP address to check.
|
|
4103
|
-
* @returns {boolean} Returns true if the IP address is reserved for private networks or localhost, otherwise false.
|
|
4104
|
-
* @public exported from `@promptbook/utils`
|
|
4105
|
-
*/
|
|
4106
|
-
function isUrlOnPrivateNetwork(url) {
|
|
4107
|
-
if (typeof url === 'string') {
|
|
4108
|
-
url = new URL(url);
|
|
4109
|
-
}
|
|
4110
|
-
return isHostnameOnPrivateNetwork(url.hostname);
|
|
4111
|
-
}
|
|
4112
|
-
|
|
4113
4062
|
/**
|
|
4114
4063
|
* Tests if given string is valid pipeline URL URL.
|
|
4115
4064
|
*
|
|
@@ -4123,16 +4072,19 @@ function isValidPipelineUrl(url) {
|
|
|
4123
4072
|
if (!isValidUrl(url)) {
|
|
4124
4073
|
return false;
|
|
4125
4074
|
}
|
|
4126
|
-
if (!url.startsWith('https://')) {
|
|
4075
|
+
if (!url.startsWith('https://') && !url.startsWith('http://') /* <- Note: [👣] */) {
|
|
4127
4076
|
return false;
|
|
4128
4077
|
}
|
|
4129
4078
|
if (url.includes('#')) {
|
|
4130
4079
|
// TODO: [🐠]
|
|
4131
4080
|
return false;
|
|
4132
4081
|
}
|
|
4082
|
+
/*
|
|
4083
|
+
Note: [👣][🧠] Is it secure to allow pipeline URLs on private and unsecured networks?
|
|
4133
4084
|
if (isUrlOnPrivateNetwork(url)) {
|
|
4134
4085
|
return false;
|
|
4135
4086
|
}
|
|
4087
|
+
*/
|
|
4136
4088
|
return true;
|
|
4137
4089
|
}
|
|
4138
4090
|
/**
|
|
@@ -12029,13 +11981,13 @@ function createCollectionFromPromise(promptbookSourcesPromiseOrFactory) {
|
|
|
12029
11981
|
*
|
|
12030
11982
|
* Note: Works only in Node.js environment because it reads the file system
|
|
12031
11983
|
*
|
|
12032
|
-
* @param
|
|
11984
|
+
* @param rootPath - path to the directory with pipelines
|
|
12033
11985
|
* @param tools - Execution tools to be used for pipeline preparation if needed - If not provided, `$provideExecutionToolsForNode` will be used
|
|
12034
11986
|
* @param options - Options for the collection creation
|
|
12035
11987
|
* @returns PipelineCollection
|
|
12036
11988
|
* @public exported from `@promptbook/node`
|
|
12037
11989
|
*/
|
|
12038
|
-
function createCollectionFromDirectory(
|
|
11990
|
+
function createCollectionFromDirectory(rootPath, tools, options) {
|
|
12039
11991
|
return __awaiter(this, void 0, void 0, function () {
|
|
12040
11992
|
var madeLibraryFilePath, _a, _b, isRecursive, _c, isVerbose, _d, isLazyLoaded, _e, isCrashedOnError, rootUrl, collection;
|
|
12041
11993
|
var _this = this;
|
|
@@ -12052,7 +12004,7 @@ function createCollectionFromDirectory(path, tools, options) {
|
|
|
12052
12004
|
throw new EnvironmentMismatchError('Can not create collection without filesystem tools');
|
|
12053
12005
|
// <- TODO: [🧠] What is the best error type here`
|
|
12054
12006
|
}
|
|
12055
|
-
madeLibraryFilePath = join(
|
|
12007
|
+
madeLibraryFilePath = join(rootPath, "".concat(DEFAULT_PIPELINE_COLLECTION_BASE_FILENAME
|
|
12056
12008
|
// <- TODO: [🦒] Allow to override (pass different value into the function)
|
|
12057
12009
|
, ".json"));
|
|
12058
12010
|
return [4 /*yield*/, isFileExisting(madeLibraryFilePath, tools.fs)];
|
|
@@ -12071,18 +12023,18 @@ function createCollectionFromDirectory(path, tools, options) {
|
|
|
12071
12023
|
switch (_b.label) {
|
|
12072
12024
|
case 0:
|
|
12073
12025
|
if (isVerbose) {
|
|
12074
|
-
console.info(colors.cyan("Creating pipeline collection from path ".concat(
|
|
12026
|
+
console.info(colors.cyan("Creating pipeline collection from path ".concat(rootPath.split('\\').join('/'))));
|
|
12075
12027
|
}
|
|
12076
|
-
return [4 /*yield*/, listAllFiles(
|
|
12028
|
+
return [4 /*yield*/, listAllFiles(rootPath, isRecursive, tools.fs)];
|
|
12077
12029
|
case 1:
|
|
12078
12030
|
fileNames = _b.sent();
|
|
12079
|
-
// Note: First load all
|
|
12080
|
-
//
|
|
12031
|
+
// Note: First load all `.book.json` and then `.book` / `.book.md` files
|
|
12032
|
+
// `.book.json` can be prepared so it is faster to load
|
|
12081
12033
|
fileNames.sort(function (a, b) {
|
|
12082
|
-
if (a.endsWith('.json') && b.endsWith('.md')) {
|
|
12034
|
+
if (a.endsWith('.json') && (b.endsWith('.book') || b.endsWith('.book.md'))) {
|
|
12083
12035
|
return -1;
|
|
12084
12036
|
}
|
|
12085
|
-
if (a.endsWith('.md') && b.endsWith('.json')) {
|
|
12037
|
+
if ((a.endsWith('.book') || a.endsWith('.book.md')) && b.endsWith('.json')) {
|
|
12086
12038
|
return 1;
|
|
12087
12039
|
}
|
|
12088
12040
|
return 0;
|
|
@@ -12099,7 +12051,7 @@ function createCollectionFromDirectory(path, tools, options) {
|
|
|
12099
12051
|
case 1:
|
|
12100
12052
|
_f.trys.push([1, 8, , 9]);
|
|
12101
12053
|
pipeline = null;
|
|
12102
|
-
if (!fileName.endsWith('.book.md')) return [3 /*break*/, 4];
|
|
12054
|
+
if (!(fileName.endsWith('.book') || fileName.endsWith('.book.md'))) return [3 /*break*/, 4];
|
|
12103
12055
|
_c = validatePipelineString;
|
|
12104
12056
|
return [4 /*yield*/, readFile(fileName, 'utf-8')];
|
|
12105
12057
|
case 2:
|
|
@@ -12131,7 +12083,8 @@ function createCollectionFromDirectory(path, tools, options) {
|
|
|
12131
12083
|
if (pipeline !== null) {
|
|
12132
12084
|
if (rootUrl !== undefined) {
|
|
12133
12085
|
if (pipeline.pipelineUrl === undefined) {
|
|
12134
|
-
pipelineUrl = rootUrl + '/' + fileName.split('\\').join('/');
|
|
12086
|
+
pipelineUrl = rootUrl + '/' + relative(rootPath, fileName).split('\\').join('/');
|
|
12087
|
+
// console.log({ pipelineUrl, rootPath, rootUrl, fileName });
|
|
12135
12088
|
if (isVerbose) {
|
|
12136
12089
|
console.info(colors.yellow("Implicitly set pipeline URL to ".concat(pipelineUrl, " from ").concat(fileName
|
|
12137
12090
|
.split('\\')
|
|
@@ -13915,6 +13868,46 @@ function startRemoteServer(options) {
|
|
|
13915
13868
|
}
|
|
13916
13869
|
});
|
|
13917
13870
|
}); });
|
|
13871
|
+
// TODO: [🧠] Is it secure / good idea to expose source codes of hosted books
|
|
13872
|
+
app.get("".concat(rootPath, "/books/*"), function (request, response) { return __awaiter(_this, void 0, void 0, function () {
|
|
13873
|
+
var pipelines, fullUrl, pipelineUrl, pipeline, source, error_1;
|
|
13874
|
+
return __generator(this, function (_a) {
|
|
13875
|
+
switch (_a.label) {
|
|
13876
|
+
case 0:
|
|
13877
|
+
_a.trys.push([0, 3, , 4]);
|
|
13878
|
+
if (collection === null) {
|
|
13879
|
+
response.status(500).send('No collection nor books available');
|
|
13880
|
+
return [2 /*return*/];
|
|
13881
|
+
}
|
|
13882
|
+
return [4 /*yield*/, collection.listPipelines()];
|
|
13883
|
+
case 1:
|
|
13884
|
+
pipelines = _a.sent();
|
|
13885
|
+
fullUrl = request.protocol + '://' + request.get('host') + request.originalUrl;
|
|
13886
|
+
pipelineUrl = pipelines.find(function (pipelineUrl) { return pipelineUrl.endsWith(request.originalUrl); }) || fullUrl;
|
|
13887
|
+
return [4 /*yield*/, collection.getPipelineByUrl(pipelineUrl)];
|
|
13888
|
+
case 2:
|
|
13889
|
+
pipeline = _a.sent();
|
|
13890
|
+
source = pipeline.sources[0];
|
|
13891
|
+
if (source === undefined || source.type !== 'BOOK') {
|
|
13892
|
+
throw new Error('Pipeline source is not a book');
|
|
13893
|
+
}
|
|
13894
|
+
response
|
|
13895
|
+
.type('text/markdown')
|
|
13896
|
+
.send(source.content);
|
|
13897
|
+
return [3 /*break*/, 4];
|
|
13898
|
+
case 3:
|
|
13899
|
+
error_1 = _a.sent();
|
|
13900
|
+
if (!(error_1 instanceof Error)) {
|
|
13901
|
+
throw error_1;
|
|
13902
|
+
}
|
|
13903
|
+
response
|
|
13904
|
+
.status(404)
|
|
13905
|
+
.send({ error: serializeError(error_1) });
|
|
13906
|
+
return [3 /*break*/, 4];
|
|
13907
|
+
case 4: return [2 /*return*/];
|
|
13908
|
+
}
|
|
13909
|
+
});
|
|
13910
|
+
}); });
|
|
13918
13911
|
app.get("".concat(rootPath, "/executions"), function (request, response) { return __awaiter(_this, void 0, void 0, function () {
|
|
13919
13912
|
return __generator(this, function (_a) {
|
|
13920
13913
|
response.send(runningExecutionTasks);
|
|
@@ -13927,7 +13920,9 @@ function startRemoteServer(options) {
|
|
|
13927
13920
|
taskId = request.params.taskId;
|
|
13928
13921
|
execution = runningExecutionTasks.find(function (executionTask) { return executionTask.taskId === taskId; });
|
|
13929
13922
|
if (execution === undefined) {
|
|
13930
|
-
response
|
|
13923
|
+
response
|
|
13924
|
+
.status(404)
|
|
13925
|
+
.send("Execution \"".concat(taskId, "\" not found"));
|
|
13931
13926
|
return [2 /*return*/];
|
|
13932
13927
|
}
|
|
13933
13928
|
response.send(execution.currentValue);
|
|
@@ -13935,7 +13930,7 @@ function startRemoteServer(options) {
|
|
|
13935
13930
|
});
|
|
13936
13931
|
}); });
|
|
13937
13932
|
app.post("".concat(rootPath, "/executions/new"), function (request, response) { return __awaiter(_this, void 0, void 0, function () {
|
|
13938
|
-
var _a, inputParameters, identification, pipelineUrl, pipeline, tools, pipelineExecutor, executionTask,
|
|
13933
|
+
var _a, inputParameters, identification, pipelineUrl, pipeline, tools, pipelineExecutor, executionTask, error_2;
|
|
13939
13934
|
return __generator(this, function (_b) {
|
|
13940
13935
|
switch (_b.label) {
|
|
13941
13936
|
case 0:
|
|
@@ -13963,11 +13958,11 @@ function startRemoteServer(options) {
|
|
|
13963
13958
|
response.send(executionTask);
|
|
13964
13959
|
return [3 /*break*/, 5];
|
|
13965
13960
|
case 4:
|
|
13966
|
-
|
|
13967
|
-
if (!(
|
|
13968
|
-
throw
|
|
13961
|
+
error_2 = _b.sent();
|
|
13962
|
+
if (!(error_2 instanceof Error)) {
|
|
13963
|
+
throw error_2;
|
|
13969
13964
|
}
|
|
13970
|
-
response.status(400).send({ error: serializeError(
|
|
13965
|
+
response.status(400).send({ error: serializeError(error_2) });
|
|
13971
13966
|
return [3 /*break*/, 5];
|
|
13972
13967
|
case 5: return [2 /*return*/];
|
|
13973
13968
|
}
|
|
@@ -13988,7 +13983,7 @@ function startRemoteServer(options) {
|
|
|
13988
13983
|
}
|
|
13989
13984
|
// -----------
|
|
13990
13985
|
socket.on('prompt-request', function (request) { return __awaiter(_this, void 0, void 0, function () {
|
|
13991
|
-
var identification, prompt, tools, llm, _a, promptResult, _b,
|
|
13986
|
+
var identification, prompt, tools, llm, _a, promptResult, _b, error_3;
|
|
13992
13987
|
return __generator(this, function (_c) {
|
|
13993
13988
|
switch (_c.label) {
|
|
13994
13989
|
case 0:
|
|
@@ -14057,11 +14052,11 @@ function startRemoteServer(options) {
|
|
|
14057
14052
|
socket.emit('prompt-response', { promptResult: promptResult } /* <- Note: [🤛] */);
|
|
14058
14053
|
return [3 /*break*/, 15];
|
|
14059
14054
|
case 13:
|
|
14060
|
-
|
|
14061
|
-
if (!(
|
|
14062
|
-
throw
|
|
14055
|
+
error_3 = _c.sent();
|
|
14056
|
+
if (!(error_3 instanceof Error)) {
|
|
14057
|
+
throw error_3;
|
|
14063
14058
|
}
|
|
14064
|
-
socket.emit('error', serializeError(
|
|
14059
|
+
socket.emit('error', serializeError(error_3) /* <- Note: [🤛] */);
|
|
14065
14060
|
return [3 /*break*/, 15];
|
|
14066
14061
|
case 14:
|
|
14067
14062
|
socket.disconnect();
|
|
@@ -14073,7 +14068,7 @@ function startRemoteServer(options) {
|
|
|
14073
14068
|
// -----------
|
|
14074
14069
|
// TODO: [👒] Listing models (and checking configuration) probbably should go through REST API not Socket.io
|
|
14075
14070
|
socket.on('listModels-request', function (request) { return __awaiter(_this, void 0, void 0, function () {
|
|
14076
|
-
var identification, tools, llm, models,
|
|
14071
|
+
var identification, tools, llm, models, error_4;
|
|
14077
14072
|
return __generator(this, function (_a) {
|
|
14078
14073
|
switch (_a.label) {
|
|
14079
14074
|
case 0:
|
|
@@ -14094,11 +14089,11 @@ function startRemoteServer(options) {
|
|
|
14094
14089
|
socket.emit('listModels-response', { models: models } /* <- Note: [🤛] */);
|
|
14095
14090
|
return [3 /*break*/, 6];
|
|
14096
14091
|
case 4:
|
|
14097
|
-
|
|
14098
|
-
if (!(
|
|
14099
|
-
throw
|
|
14092
|
+
error_4 = _a.sent();
|
|
14093
|
+
if (!(error_4 instanceof Error)) {
|
|
14094
|
+
throw error_4;
|
|
14100
14095
|
}
|
|
14101
|
-
socket.emit('error', serializeError(
|
|
14096
|
+
socket.emit('error', serializeError(error_4));
|
|
14102
14097
|
return [3 /*break*/, 6];
|
|
14103
14098
|
case 5:
|
|
14104
14099
|
socket.disconnect();
|
|
@@ -14110,7 +14105,7 @@ function startRemoteServer(options) {
|
|
|
14110
14105
|
// -----------
|
|
14111
14106
|
// TODO: [👒] Listing models (and checking configuration) probbably should go through REST API not Socket.io
|
|
14112
14107
|
socket.on('preparePipeline-request', function (request) { return __awaiter(_this, void 0, void 0, function () {
|
|
14113
|
-
var identification, pipeline, tools, preparedPipeline,
|
|
14108
|
+
var identification, pipeline, tools, preparedPipeline, error_5;
|
|
14114
14109
|
return __generator(this, function (_a) {
|
|
14115
14110
|
switch (_a.label) {
|
|
14116
14111
|
case 0:
|
|
@@ -14130,11 +14125,11 @@ function startRemoteServer(options) {
|
|
|
14130
14125
|
socket.emit('preparePipeline-response', { preparedPipeline: preparedPipeline } /* <- Note: [🤛] */);
|
|
14131
14126
|
return [3 /*break*/, 6];
|
|
14132
14127
|
case 4:
|
|
14133
|
-
|
|
14134
|
-
if (!(
|
|
14135
|
-
throw
|
|
14128
|
+
error_5 = _a.sent();
|
|
14129
|
+
if (!(error_5 instanceof Error)) {
|
|
14130
|
+
throw error_5;
|
|
14136
14131
|
}
|
|
14137
|
-
socket.emit('error', serializeError(
|
|
14132
|
+
socket.emit('error', serializeError(error_5));
|
|
14138
14133
|
return [3 /*break*/, 6];
|
|
14139
14134
|
case 5:
|
|
14140
14135
|
socket.disconnect();
|