@promptbook/cli 0.85.0-0 → 0.85.0-2

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.
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  // <- TODO: [🎺] Ensure correct version of Node.js is used
3
+ // promptbook-cli.js
3
4
 
4
5
  /**
5
6
  * Note: [🔺] Purpose of this file is to run CLI in production environment
package/esm/index.es.js CHANGED
@@ -2,12 +2,12 @@ import colors from 'colors';
2
2
  import commander from 'commander';
3
3
  import spaceTrim, { spaceTrim as spaceTrim$1 } from 'spacetrim';
4
4
  import { forTime } from 'waitasecond';
5
- import { basename, join, dirname } from 'path';
6
- import { stat, access, constants, readFile, writeFile, readdir, mkdir, unlink, rm, rmdir, rename } from 'fs/promises';
5
+ import { basename, join, dirname } from 'node:path';
6
+ import { stat, access, constants, readFile, writeFile, readdir, mkdir, unlink, rm, rmdir, rename } from 'node:fs/promises';
7
7
  import hexEncoder from 'crypto-js/enc-hex';
8
8
  import sha256 from 'crypto-js/sha256';
9
9
  import * as dotenv from 'dotenv';
10
- import { spawn } from 'child_process';
10
+ import { spawn } from 'node:child_process';
11
11
  import { format } from 'prettier';
12
12
  import parserHtml from 'prettier/parser-html';
13
13
  import { BehaviorSubject, concat, from } from 'rxjs';
@@ -19,7 +19,7 @@ import glob from 'glob-promise';
19
19
  import prompts from 'prompts';
20
20
  import moment from 'moment';
21
21
  import express from 'express';
22
- import http from 'http';
22
+ import http from 'node:http';
23
23
  import { Server } from 'socket.io';
24
24
  import { io } from 'socket.io-client';
25
25
  import Anthropic from '@anthropic-ai/sdk';
@@ -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.84.0';
46
+ var PROMPTBOOK_ENGINE_VERSION = '0.85.0-1';
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
@@ -4921,9 +4921,9 @@ function assertsTaskSuccessful(executionResult) {
4921
4921
  function createTask(options) {
4922
4922
  var taskType = options.taskType, taskProcessCallback = options.taskProcessCallback;
4923
4923
  var taskId = "".concat(taskType.toLowerCase(), "-").concat($randomToken(256 /* <- TODO: !!! To global config */));
4924
- var resultSubject = new BehaviorSubject({});
4924
+ var partialResultSubject = new BehaviorSubject({});
4925
4925
  var finalResultPromise = /* not await */ taskProcessCallback(function (newOngoingResult) {
4926
- resultSubject.next(newOngoingResult);
4926
+ partialResultSubject.next(newOngoingResult);
4927
4927
  });
4928
4928
  function asPromise(options) {
4929
4929
  return __awaiter(this, void 0, void 0, function () {
@@ -4948,7 +4948,7 @@ function createTask(options) {
4948
4948
  taskId: taskId,
4949
4949
  asPromise: asPromise,
4950
4950
  asObservable: function () {
4951
- return concat(resultSubject.asObservable(), from(asPromise({
4951
+ return concat(partialResultSubject.asObservable(), from(asPromise({
4952
4952
  isCrashedOnError: true,
4953
4953
  })));
4954
4954
  },
@@ -11416,6 +11416,17 @@ function normalizeWhitespaces(sentence) {
11416
11416
  return sentence.replace(/\s+/gs, ' ').trim();
11417
11417
  }
11418
11418
 
11419
+ /**
11420
+ * Adds suffix to the URL
11421
+ *
11422
+ * @public exported from `@promptbook/utils`
11423
+ */
11424
+ function suffixUrl(value, suffix) {
11425
+ var baseUrl = value.href.endsWith('/') ? value.href.slice(0, -1) : value.href;
11426
+ var normalizedSuffix = suffix.replace(/\/+/g, '/');
11427
+ return (baseUrl + normalizedSuffix);
11428
+ }
11429
+
11419
11430
  /**
11420
11431
  * Function trimCodeBlock will trim starting and ending code block from the string if it is present.
11421
11432
  *
@@ -13508,9 +13519,9 @@ function $initializeRunCommand(program) {
13508
13519
  case 17:
13509
13520
  executionTask = _m.sent();
13510
13521
  if (isVerbose) {
13511
- executionTask.asObservable().subscribe(function (progress) {
13522
+ executionTask.asObservable().subscribe(function (partialResult) {
13512
13523
  console.info(colors.gray('--- Progress ---'));
13513
- console.info(progress);
13524
+ console.info(partialResult);
13514
13525
  });
13515
13526
  }
13516
13527
  return [4 /*yield*/, executionTask.asPromise({
@@ -13746,11 +13757,33 @@ function $initializeTestCommand(program) {
13746
13757
  */
13747
13758
  function startRemoteServer(options) {
13748
13759
  var _this = this;
13749
- var _a = __assign({ isAnonymousModeAllowed: false, isApplicationModeAllowed: false, collection: null, createLlmExecutionTools: null }, options), port = _a.port, path = _a.path, collection = _a.collection, createLlmExecutionTools = _a.createLlmExecutionTools, isAnonymousModeAllowed = _a.isAnonymousModeAllowed, isApplicationModeAllowed = _a.isApplicationModeAllowed, _b = _a.isVerbose, isVerbose = _b === void 0 ? DEFAULT_IS_VERBOSE : _b;
13760
+ var _a = __assign({ isAnonymousModeAllowed: false, isApplicationModeAllowed: false, collection: null, createLlmExecutionTools: null }, options), port = _a.port, collection = _a.collection, createLlmExecutionTools = _a.createLlmExecutionTools, isAnonymousModeAllowed = _a.isAnonymousModeAllowed, isApplicationModeAllowed = _a.isApplicationModeAllowed, _b = _a.isVerbose, isVerbose = _b === void 0 ? DEFAULT_IS_VERBOSE : _b;
13750
13761
  // <- TODO: [🦪] Some helper type to be able to use discriminant union types with destructuring
13762
+ var _c = options.rootPath, rootPath = _c === void 0 ? '/' : _c;
13763
+ if (!rootPath.startsWith('/')) {
13764
+ rootPath = "/".concat(rootPath);
13765
+ } /* not else */
13766
+ if (rootPath.endsWith('/')) {
13767
+ rootPath = rootPath.slice(0, -1);
13768
+ } /* not else */
13769
+ if (rootPath === '/') {
13770
+ rootPath = '';
13771
+ }
13772
+ var socketioPath = '/' +
13773
+ "".concat(rootPath, "/socket.io")
13774
+ .split('/')
13775
+ .filter(function (part) { return part !== ''; })
13776
+ .join('/');
13777
+ var startupDate = new Date();
13751
13778
  var app = express();
13752
13779
  app.use(express.json());
13753
- app.get('/', function (request, response) { return __awaiter(_this, void 0, void 0, function () {
13780
+ app.use(function (request, response, next) {
13781
+ response.setHeader('X-Powered-By', 'Promptbook engine');
13782
+ next();
13783
+ });
13784
+ var runningExecutionTasks = [];
13785
+ // TODO: !!!!!! Do here some garbage collection of finished tasks
13786
+ app.get(['/', rootPath], function (request, response) { return __awaiter(_this, void 0, void 0, function () {
13754
13787
  var _a, _b;
13755
13788
  var _this = this;
13756
13789
  var _c;
@@ -13760,20 +13793,19 @@ function startRemoteServer(options) {
13760
13793
  if ((_c = request.url) === null || _c === void 0 ? void 0 : _c.includes('socket.io')) {
13761
13794
  return [2 /*return*/];
13762
13795
  }
13763
- _b = (_a = response).send;
13764
- // TODO: !!!!!! Make this either valid html or text - http://localhost:4460/
13796
+ _b = (_a = response.type('text/markdown')).send;
13765
13797
  return [4 /*yield*/, spaceTrim$1(function (block) { return __awaiter(_this, void 0, void 0, function () {
13766
13798
  var _a, _b, _c, _d, _e;
13767
13799
  return __generator(this, function (_f) {
13768
13800
  switch (_f.label) {
13769
13801
  case 0:
13770
- _b = (_a = "\n Server for processing promptbook remote requests is running.\n\n Version: ".concat(PROMPTBOOK_ENGINE_VERSION, "\n Socket.io path: ").concat(path, "/socket.io\n Anonymouse mode: ").concat(isAnonymousModeAllowed ? 'enabled' : 'disabled', "\n Application mode: ").concat(isApplicationModeAllowed ? 'enabled' : 'disabled', "\n ")).concat;
13802
+ _b = (_a = "\n # Promptbook\n\n > ".concat(block(CLAIM), "\n\n **Book language version:** ").concat(BOOK_LANGUAGE_VERSION, "\n **Promptbook engine version:** ").concat(PROMPTBOOK_ENGINE_VERSION, "\n **Node.js version:** ").concat(process.version /* <- TODO: [🧠] Is it secure to expose this */, "\n\n ---\n\n ## Details\n\n **Server port:** ").concat(port, "\n **Server root path:** ").concat(rootPath, "\n **Socket.io path:** ").concat(socketioPath, "\n **Startup date:** ").concat(startupDate.toISOString(), "\n **Anonymouse mode:** ").concat(isAnonymousModeAllowed ? 'enabled' : 'disabled', "\n **Application mode:** ").concat(isApplicationModeAllowed ? 'enabled' : 'disabled', "\n ")).concat;
13771
13803
  _c = block;
13772
13804
  if (!(!isApplicationModeAllowed || collection === null)) return [3 /*break*/, 1];
13773
13805
  _d = '';
13774
13806
  return [3 /*break*/, 3];
13775
13807
  case 1:
13776
- _e = 'Pipelines in collection:\n';
13808
+ _e = '**Pipelines in collection:**\n';
13777
13809
  return [4 /*yield*/, collection.listPipelines()];
13778
13810
  case 2:
13779
13811
  _d = _e +
@@ -13781,27 +13813,49 @@ function startRemoteServer(options) {
13781
13813
  .map(function (pipelineUrl) { return "- ".concat(pipelineUrl); })
13782
13814
  .join('\n');
13783
13815
  _f.label = 3;
13784
- case 3: return [2 /*return*/, _b.apply(_a, [_c.apply(void 0, [_d]), "\n\n For more information look at:\n https://github.com/webgptorg/promptbook\n "])];
13816
+ case 3: return [2 /*return*/, _b.apply(_a, [_c.apply(void 0, [_d]), "\n **Running executions:** "]).concat(runningExecutionTasks.length, "\n\n ---\n\n ## Paths\n\n ").concat(block(app._router.stack
13817
+ .map(function (_a) {
13818
+ var route = _a.route;
13819
+ return (route === null || route === void 0 ? void 0 : route.path) || null;
13820
+ })
13821
+ .filter(function (path) { return path !== null; })
13822
+ .map(function (path) { return "- ".concat(path); })
13823
+ .join('\n')), "\n\n ---\n\n ## Instructions\n\n To connect to this server use:\n\n 1) The client https://www.npmjs.com/package/@promptbook/remote-client\n 2) OpenAI compatible client *(Not wotking yet)*\n 3) REST API\n\n For more information look at:\n https://github.com/webgptorg/promptbook\n ")];
13785
13824
  }
13786
13825
  });
13787
13826
  }); })];
13788
13827
  case 1:
13789
- _b.apply(_a, [
13790
- // TODO: !!!!!! Make this either valid html or text - http://localhost:4460/
13791
- _d.sent()]);
13828
+ _b.apply(_a, [_d.sent()]);
13792
13829
  return [2 /*return*/];
13793
13830
  }
13794
13831
  });
13795
13832
  }); });
13796
- var runningExecutionTasks = [];
13797
- // TODO: !!!!!! Do here some garbage collection of finished tasks
13798
- app.get('/executions', function (request, response) { return __awaiter(_this, void 0, void 0, function () {
13833
+ app.get("".concat(rootPath, "/books"), function (request, response) { return __awaiter(_this, void 0, void 0, function () {
13834
+ var _a, _b, _c;
13835
+ return __generator(this, function (_d) {
13836
+ switch (_d.label) {
13837
+ case 0:
13838
+ _b = (_a = response).send;
13839
+ if (!(collection === null)) return [3 /*break*/, 1];
13840
+ _c = [];
13841
+ return [3 /*break*/, 3];
13842
+ case 1: return [4 /*yield*/, collection.listPipelines()];
13843
+ case 2:
13844
+ _c = _d.sent();
13845
+ _d.label = 3;
13846
+ case 3:
13847
+ _b.apply(_a, [_c]);
13848
+ return [2 /*return*/];
13849
+ }
13850
+ });
13851
+ }); });
13852
+ app.get("".concat(rootPath, "/executions"), function (request, response) { return __awaiter(_this, void 0, void 0, function () {
13799
13853
  return __generator(this, function (_a) {
13800
13854
  response.send(runningExecutionTasks);
13801
13855
  return [2 /*return*/];
13802
13856
  });
13803
13857
  }); });
13804
- app.get('/executions/:taskId', function (request, response) { return __awaiter(_this, void 0, void 0, function () {
13858
+ app.get("".concat(rootPath, "/executions/:taskId"), function (request, response) { return __awaiter(_this, void 0, void 0, function () {
13805
13859
  var taskId, execution;
13806
13860
  return __generator(this, function (_a) {
13807
13861
  taskId = request.query.taskId;
@@ -13814,16 +13868,17 @@ function startRemoteServer(options) {
13814
13868
  return [2 /*return*/];
13815
13869
  });
13816
13870
  }); });
13817
- app.post('/executions/new', function (request, response) { return __awaiter(_this, void 0, void 0, function () {
13818
- var _a, pipelineUrl, inputParameters, pipeline, llm, fs, executables, tools, pipelineExecutor, executionTask;
13819
- var _b;
13820
- return __generator(this, function (_c) {
13821
- switch (_c.label) {
13871
+ app.post("".concat(rootPath, "/executions/new"), function (request, response) { return __awaiter(_this, void 0, void 0, function () {
13872
+ var inputParameters, pipelineUrl, pipeline, llm, fs, executables, tools, pipelineExecutor, executionTask;
13873
+ var _a;
13874
+ return __generator(this, function (_b) {
13875
+ switch (_b.label) {
13822
13876
  case 0:
13823
- _a = request.body, pipelineUrl = _a.pipelineUrl, inputParameters = _a.inputParameters;
13877
+ inputParameters = request.body.inputParameters;
13878
+ pipelineUrl = request.body.pipelineUrl || request.body.book;
13824
13879
  return [4 /*yield*/, (collection === null || collection === void 0 ? void 0 : collection.getPipelineByUrl(pipelineUrl))];
13825
13880
  case 1:
13826
- pipeline = _c.sent();
13881
+ pipeline = _b.sent();
13827
13882
  if (pipeline === undefined) {
13828
13883
  response.status(404).send("Pipeline \"".concat(pipelineUrl, "\" not found"));
13829
13884
  return [2 /*return*/];
@@ -13834,19 +13889,19 @@ function startRemoteServer(options) {
13834
13889
  customOptions: {},
13835
13890
  })];
13836
13891
  case 2:
13837
- llm = _c.sent();
13892
+ llm = _b.sent();
13838
13893
  fs = $provideFilesystemForNode();
13839
13894
  return [4 /*yield*/, $provideExecutablesForNode()];
13840
13895
  case 3:
13841
- executables = _c.sent();
13842
- _b = {
13896
+ executables = _b.sent();
13897
+ _a = {
13843
13898
  llm: llm,
13844
13899
  fs: fs
13845
13900
  };
13846
13901
  return [4 /*yield*/, $provideScrapersForNode({ fs: fs, llm: llm, executables: executables })];
13847
13902
  case 4:
13848
- tools = (_b.scrapers = _c.sent(),
13849
- _b);
13903
+ tools = (_a.scrapers = _b.sent(),
13904
+ _a);
13850
13905
  pipelineExecutor = createPipelineExecutor(__assign({ pipeline: pipeline, tools: tools }, options));
13851
13906
  executionTask = pipelineExecutor(inputParameters);
13852
13907
  runningExecutionTasks.push(executionTask);
@@ -13857,7 +13912,7 @@ function startRemoteServer(options) {
13857
13912
  }); });
13858
13913
  var httpServer = http.createServer(app);
13859
13914
  var server = new Server(httpServer, {
13860
- path: path,
13915
+ path: socketioPath,
13861
13916
  transports: [/*'websocket', <- TODO: [🌬] Make websocket transport work */ 'polling'],
13862
13917
  cors: {
13863
13918
  origin: '*',
@@ -14101,6 +14156,8 @@ function startRemoteServer(options) {
14101
14156
  };
14102
14157
  }
14103
14158
  /**
14159
+ * TODO: !!!!!!! CORS and security
14160
+ * TODO: !!!!!!! Allow to pass tokem here
14104
14161
  * TODO: [👩🏾‍🤝‍🧑🏾] Allow to pass custom fetch function here - PromptbookFetch
14105
14162
  * TODO: Split this file into multiple functions - handler for each request
14106
14163
  * TODO: Maybe use `$exportJson`
@@ -14124,21 +14181,80 @@ function startRemoteServer(options) {
14124
14181
  function $initializeStartServerCommand(program) {
14125
14182
  var _this = this;
14126
14183
  var startServerCommand = program.command('start-server');
14184
+ startServerCommand.argument('[path]',
14185
+ // <- TODO: [🧟‍♂️] Unite path to promptbook collection argument
14186
+ 'Path to promptbook collection directory', DEFAULT_BOOKS_DIRNAME);
14127
14187
  startServerCommand.option('--port <port>', "Port to start the server on", '4460');
14128
- startServerCommand.description(spaceTrim("\n @@@\n "));
14129
- startServerCommand.action(function (_a) {
14130
- var port = _a.port;
14188
+ startServerCommand.option('-u, --url', spaceTrim("\n Public root url of the server\n It is used for following purposes:\n\n 1) It is suffixed with /books and used as rootUrl for all served books\n 2) Path (if not just /) is used as rootPath for the server\n "));
14189
+ startServerCommand.option('--allow-anonymous', "Is anonymous mode allowed", false);
14190
+ startServerCommand.option('-r, --reload', "Call LLM models even if same prompt with result is in the cache", false);
14191
+ startServerCommand.option('-v, --verbose', "Is output verbose", false);
14192
+ startServerCommand.description(spaceTrim("\n Starts a remote server to execute books\n "));
14193
+ startServerCommand.action(function (path, _a) {
14194
+ var port = _a.port, rawUrl = _a.url, isAnonymousModeAllowed = _a.allowAnonymous, isCacheReloaded = _a.reload, isVerbose = _a.verbose;
14131
14195
  return __awaiter(_this, void 0, void 0, function () {
14132
- return __generator(this, function (_b) {
14133
- startRemoteServer({
14134
- path: '/promptbook',
14135
- port: parseInt(port, 10),
14136
- isAnonymousModeAllowed: true,
14137
- isApplicationModeAllowed: true,
14138
- // <- TODO: !!!!!!
14139
- });
14140
- console.error(colors.green("Server started on port ".concat(port)));
14141
- return [2 /*return*/];
14196
+ var url, rootUrl, rootPath, prepareAndScrapeOptions, fs, llm, executables, tools, collection;
14197
+ var _b;
14198
+ return __generator(this, function (_c) {
14199
+ switch (_c.label) {
14200
+ case 0:
14201
+ url = !rawUrl ? null : new URL(rawUrl);
14202
+ if (url !== null && url.port !== port) {
14203
+ console.warn(colors.yellow("Port in --url is different from --port which the server will listen on, this is ok only if you proxy from one port to another, for exaple via nginx or docker"));
14204
+ }
14205
+ rootUrl = undefined;
14206
+ if (url !== null) {
14207
+ rootUrl = suffixUrl(url, '/books');
14208
+ }
14209
+ rootPath = '/';
14210
+ if (url !== null) {
14211
+ rootPath = url.pathname;
14212
+ }
14213
+ prepareAndScrapeOptions = {
14214
+ isVerbose: isVerbose,
14215
+ isCacheReloaded: isCacheReloaded,
14216
+ };
14217
+ fs = $provideFilesystemForNode(prepareAndScrapeOptions);
14218
+ return [4 /*yield*/, $provideLlmToolsForWizzardOrCli(prepareAndScrapeOptions)];
14219
+ case 1:
14220
+ llm = _c.sent();
14221
+ return [4 /*yield*/, $provideExecutablesForNode(prepareAndScrapeOptions)];
14222
+ case 2:
14223
+ executables = _c.sent();
14224
+ _b = {
14225
+ llm: llm,
14226
+ fs: fs
14227
+ };
14228
+ return [4 /*yield*/, $provideScrapersForNode({ fs: fs, llm: llm, executables: executables }, prepareAndScrapeOptions)];
14229
+ case 3:
14230
+ tools = (_b.scrapers = _c.sent(),
14231
+ _b.script = [
14232
+ /*new JavascriptExecutionTools(options)*/
14233
+ ],
14234
+ _b);
14235
+ return [4 /*yield*/, createCollectionFromDirectory(path, tools, {
14236
+ isVerbose: isVerbose,
14237
+ rootUrl: rootUrl,
14238
+ isRecursive: true,
14239
+ isLazyLoaded: false,
14240
+ isCrashedOnError: true,
14241
+ // <- TODO: [🍖] Add `intermediateFilesStrategy`
14242
+ })];
14243
+ case 4:
14244
+ collection = _c.sent();
14245
+ startRemoteServer({
14246
+ rootPath: rootPath,
14247
+ port: parseInt(port, 10),
14248
+ isAnonymousModeAllowed: isAnonymousModeAllowed,
14249
+ isApplicationModeAllowed: true,
14250
+ collection: collection,
14251
+ createLlmExecutionTools: function (options) {
14252
+ options.appId; options.userId;
14253
+ return llm;
14254
+ },
14255
+ });
14256
+ return [2 /*return*/];
14257
+ }
14142
14258
  });
14143
14259
  });
14144
14260
  });