@promptbook/remote-server 0.89.0-20 → 0.89.0-28

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/esm/index.es.js CHANGED
@@ -3,7 +3,7 @@ import express from 'express';
3
3
  import http from 'http';
4
4
  import { Server } from 'socket.io';
5
5
  import spaceTrim, { spaceTrim as spaceTrim$1 } from 'spacetrim';
6
- import swaggerJsdoc from 'swagger-jsdoc';
6
+ import * as OpenApiValidator from 'express-openapi-validator';
7
7
  import swaggerUi from 'swagger-ui-express';
8
8
  import { forTime } from 'waitasecond';
9
9
  import { randomBytes } from 'crypto';
@@ -33,7 +33,7 @@ const BOOK_LANGUAGE_VERSION = '1.0.0';
33
33
  * @generated
34
34
  * @see https://github.com/webgptorg/promptbook
35
35
  */
36
- const PROMPTBOOK_ENGINE_VERSION = '0.89.0-20';
36
+ const PROMPTBOOK_ENGINE_VERSION = '0.89.0-28';
37
37
  /**
38
38
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
39
39
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -6778,6 +6778,198 @@ async function $provideScriptingForNode(options) {
6778
6778
  * Note: [🟢] Code in this file should never be never released in packages that could be imported into browser environment
6779
6779
  */
6780
6780
 
6781
+ // TODO: !!! List running services from REMOTE_SERVER_URLS
6782
+ // TODO: !!! Import directly from YML
6783
+ /**
6784
+ * @private !!!! Decide how to expose this
6785
+ */
6786
+ const openapiJson = {
6787
+ openapi: '3.0.0',
6788
+ info: {
6789
+ title: 'Promptbook Remote Server API (!!! From TS)',
6790
+ version: '1.0.0',
6791
+ description: 'API documentation for the Promptbook Remote Server',
6792
+ },
6793
+ paths: {
6794
+ '/': {
6795
+ get: {
6796
+ summary: 'Get server details',
6797
+ description: 'Returns details about the Promptbook server.',
6798
+ responses: {
6799
+ '200': {
6800
+ description: 'Server details in markdown format.',
6801
+ },
6802
+ },
6803
+ },
6804
+ },
6805
+ '/login': {
6806
+ post: {
6807
+ summary: 'Login to the server',
6808
+ description: 'Login to the server and get identification.',
6809
+ requestBody: {
6810
+ required: true,
6811
+ content: {
6812
+ 'application/json': {
6813
+ schema: {
6814
+ type: 'object',
6815
+ properties: {
6816
+ username: {
6817
+ type: 'string',
6818
+ },
6819
+ password: {
6820
+ type: 'string',
6821
+ },
6822
+ appId: {
6823
+ type: 'string',
6824
+ },
6825
+ },
6826
+ },
6827
+ },
6828
+ },
6829
+ },
6830
+ responses: {
6831
+ '200': {
6832
+ description: 'Successful login',
6833
+ content: {
6834
+ 'application/json': {
6835
+ schema: {
6836
+ type: 'object',
6837
+ properties: {
6838
+ identification: {
6839
+ type: 'object',
6840
+ },
6841
+ },
6842
+ },
6843
+ },
6844
+ },
6845
+ },
6846
+ },
6847
+ },
6848
+ },
6849
+ '/books': {
6850
+ get: {
6851
+ summary: 'List all books',
6852
+ description: 'Returns a list of all available books in the collection.',
6853
+ responses: {
6854
+ '200': {
6855
+ description: 'A list of books.',
6856
+ content: {
6857
+ 'application/json': {
6858
+ schema: {
6859
+ type: 'array',
6860
+ items: {
6861
+ type: 'string',
6862
+ },
6863
+ },
6864
+ },
6865
+ },
6866
+ },
6867
+ },
6868
+ },
6869
+ },
6870
+ '/books/{bookId}': {
6871
+ get: {
6872
+ summary: 'Get book content',
6873
+ description: 'Returns the content of a specific book.',
6874
+ parameters: [
6875
+ {
6876
+ in: 'path',
6877
+ name: 'bookId',
6878
+ required: true,
6879
+ schema: {
6880
+ type: 'string',
6881
+ },
6882
+ description: 'The ID of the book to retrieve.',
6883
+ },
6884
+ ],
6885
+ responses: {
6886
+ '200': {
6887
+ description: 'The content of the book.',
6888
+ content: {
6889
+ 'text/markdown': {
6890
+ schema: {
6891
+ type: 'string',
6892
+ },
6893
+ },
6894
+ },
6895
+ },
6896
+ '404': {
6897
+ description: 'Book not found.',
6898
+ },
6899
+ },
6900
+ },
6901
+ },
6902
+ '/executions': {
6903
+ get: {
6904
+ summary: 'List all executions',
6905
+ description: 'Returns a list of all running execution tasks.',
6906
+ responses: {
6907
+ '200': {
6908
+ description: 'A list of execution tasks.',
6909
+ content: {
6910
+ 'application/json': {
6911
+ schema: {
6912
+ type: 'array',
6913
+ items: {
6914
+ type: 'object',
6915
+ },
6916
+ },
6917
+ },
6918
+ },
6919
+ },
6920
+ },
6921
+ },
6922
+ },
6923
+ '/executions/new': {
6924
+ post: {
6925
+ summary: 'Start a new execution',
6926
+ description: 'Starts a new execution task for a given pipeline.',
6927
+ requestBody: {
6928
+ required: true,
6929
+ content: {
6930
+ 'application/json': {
6931
+ schema: {
6932
+ type: 'object',
6933
+ properties: {
6934
+ pipelineUrl: {
6935
+ type: 'string',
6936
+ },
6937
+ inputParameters: {
6938
+ type: 'object',
6939
+ },
6940
+ identification: {
6941
+ type: 'object',
6942
+ },
6943
+ },
6944
+ },
6945
+ },
6946
+ },
6947
+ },
6948
+ responses: {
6949
+ '200': {
6950
+ description: 'The newly created execution task.',
6951
+ content: {
6952
+ 'application/json': {
6953
+ schema: {
6954
+ type: 'object',
6955
+ },
6956
+ },
6957
+ },
6958
+ },
6959
+ '400': {
6960
+ description: 'Invalid input.',
6961
+ },
6962
+ },
6963
+ },
6964
+ },
6965
+ },
6966
+ components: {},
6967
+ tags: [],
6968
+ };
6969
+ /**
6970
+ * Note: [💞] Ignore a discrepancy between file name and entity name
6971
+ */
6972
+
6781
6973
  /**
6782
6974
  * Remote server is a proxy server that uses its execution tools internally and exposes the executor interface externally.
6783
6975
  *
@@ -6796,22 +6988,6 @@ function startRemoteServer(options) {
6796
6988
  login: null,
6797
6989
  ...options,
6798
6990
  };
6799
- // <- TODO: [🦪] Some helper type to be able to use discriminant union types with destructuring
6800
- let { rootPath = '/' } = options;
6801
- if (!rootPath.startsWith('/')) {
6802
- rootPath = `/${rootPath}`;
6803
- } /* not else */
6804
- if (rootPath.endsWith('/')) {
6805
- rootPath = rootPath.slice(0, -1);
6806
- } /* not else */
6807
- if (rootPath === '/') {
6808
- rootPath = '';
6809
- }
6810
- const socketioPath = '/' +
6811
- `${rootPath}/socket.io`
6812
- .split('/')
6813
- .filter((part) => part !== '')
6814
- .join('/');
6815
6991
  const startupDate = new Date();
6816
6992
  async function getExecutionToolsFromIdentification(identification) {
6817
6993
  if (identification === null || identification === undefined) {
@@ -6868,39 +7044,34 @@ function startRemoteServer(options) {
6868
7044
  response.setHeader('X-Powered-By', 'Promptbook engine');
6869
7045
  next();
6870
7046
  });
6871
- const swaggerOptions = {
6872
- definition: {
6873
- openapi: '3.0.0',
6874
- info: {
6875
- title: 'Promptbook Remote Server API',
6876
- version: '1.0.0',
6877
- description: 'API documentation for the Promptbook Remote Server',
6878
- },
6879
- servers: [
6880
- {
6881
- url: `http://localhost:${port}${rootPath}`,
6882
- // <- TODO: !!!!! Probbably: Pass `remoteServerUrl` instead of `port` and `rootPath`
6883
- },
6884
- ],
7047
+ // TODO: !!! Expose openapiJson to consumer and also allow to add new routes
7048
+ app.use(OpenApiValidator.middleware({
7049
+ apiSpec: openapiJson,
7050
+ // TODO: !!! Adjust
7051
+ ignorePaths(...args) {
7052
+ console.warn(`!!! Ignoring paths`, ...args);
7053
+ return true;
6885
7054
  },
6886
- apis: ['./src/remote-server/**/*.ts'], // Adjust path as needed
6887
- };
6888
- const swaggerSpec = swaggerJsdoc(swaggerOptions);
6889
- app.use([`/api-docs`, `${rootPath}/api-docs`], swaggerUi.serve, swaggerUi.setup(swaggerSpec));
7055
+ // TODO: !!! Validate both
7056
+ validateRequests: false,
7057
+ validateResponses: false, // false by default
7058
+ }));
7059
+ app.use([`/api-docs`, `/swagger`], swaggerUi.serve, swaggerUi.setup(openapiJson, {
7060
+ // customCss: '.swagger-ui .topbar { display: none }',
7061
+ // customSiteTitle: 'BRJ API',
7062
+ // customfavIcon: 'https://brj.app/favicon.ico',
7063
+ }));
7064
+ app.get(`/openapi`, (request, response) => {
7065
+ response.json(openapiJson);
7066
+ });
7067
+ // TODO: !!! Remove:
7068
+ app.get(`/xxx`, (request, response) => {
7069
+ response.json(openapiJson);
7070
+ });
6890
7071
  const runningExecutionTasks = [];
6891
7072
  // <- TODO: [🤬] Identify the users
6892
7073
  // TODO: [🧠] Do here some garbage collection of finished tasks
6893
- /**
6894
- * @swagger
6895
- * /:
6896
- * get:
6897
- * summary: Get server details
6898
- * description: Returns details about the Promptbook server.
6899
- * responses:
6900
- * 200:
6901
- * description: Server details in markdown format.
6902
- */
6903
- app.get(['/', rootPath], async (request, response) => {
7074
+ app.get('/', async (request, response) => {
6904
7075
  var _a;
6905
7076
  if ((_a = request.url) === null || _a === void 0 ? void 0 : _a.includes('socket.io')) {
6906
7077
  return;
@@ -6919,8 +7090,6 @@ function startRemoteServer(options) {
6919
7090
  ## Details
6920
7091
 
6921
7092
  **Server port:** ${port}
6922
- **Server root path:** ${rootPath}
6923
- **Socket.io path:** ${socketioPath}
6924
7093
  **Startup date:** ${startupDate.toISOString()}
6925
7094
  **Anonymouse mode:** ${isAnonymousModeAllowed ? 'enabled' : 'disabled'}
6926
7095
  **Application mode:** ${isApplicationModeAllowed ? 'enabled' : 'disabled'}
@@ -6959,38 +7128,7 @@ function startRemoteServer(options) {
6959
7128
  https://github.com/webgptorg/promptbook
6960
7129
  `));
6961
7130
  });
6962
- /**
6963
- * @swagger
6964
- *
6965
- * /login:
6966
- * post:
6967
- * summary: Login to the server
6968
- * description: Login to the server and get identification.
6969
- * requestBody:
6970
- * required: true
6971
- * content:
6972
- * application/json:
6973
- * schema:
6974
- * type: object
6975
- * properties:
6976
- * username:
6977
- * type: string
6978
- * password:
6979
- * type: string
6980
- * appId:
6981
- * type: string
6982
- * responses:
6983
- * 200:
6984
- * description: Successful login
6985
- * content:
6986
- * application/json:
6987
- * schema:
6988
- * type: object
6989
- * properties:
6990
- * identification:
6991
- * type: object
6992
- */
6993
- app.post([`/login`, `${rootPath}/login`], async (request, response) => {
7131
+ app.post(`/login`, async (request, response) => {
6994
7132
  if (!isApplicationModeAllowed || login === null) {
6995
7133
  response.status(400).send('Application mode is not allowed');
6996
7134
  return;
@@ -7030,23 +7168,7 @@ function startRemoteServer(options) {
7030
7168
  response.status(400).send({ error: serializeError(error) });
7031
7169
  }
7032
7170
  });
7033
- /**
7034
- * @swagger
7035
- * /books:
7036
- * get:
7037
- * summary: List all books
7038
- * description: Returns a list of all available books in the collection.
7039
- * responses:
7040
- * 200:
7041
- * description: A list of books.
7042
- * content:
7043
- * application/json:
7044
- * schema:
7045
- * type: array
7046
- * items:
7047
- * type: string
7048
- */
7049
- app.get([`/books`, `${rootPath}/books`], async (request, response) => {
7171
+ app.get(`/books`, async (request, response) => {
7050
7172
  if (collection === null) {
7051
7173
  response.status(500).send('No collection available');
7052
7174
  return;
@@ -7056,30 +7178,7 @@ function startRemoteServer(options) {
7056
7178
  response.send(pipelines);
7057
7179
  });
7058
7180
  // TODO: [🧠] Is it secure / good idea to expose source codes of hosted books
7059
- /**
7060
- * @swagger
7061
- * /books/{bookId}:
7062
- * get:
7063
- * summary: Get book content
7064
- * description: Returns the content of a specific book.
7065
- * parameters:
7066
- * - in: path
7067
- * name: bookId
7068
- * required: true
7069
- * schema:
7070
- * type: string
7071
- * description: The ID of the book to retrieve.
7072
- * responses:
7073
- * 200:
7074
- * description: The content of the book.
7075
- * content:
7076
- * text/markdown:
7077
- * schema:
7078
- * type: string
7079
- * 404:
7080
- * description: Book not found.
7081
- */
7082
- app.get([`/books/*`, `${rootPath}/books/*`], async (request, response) => {
7181
+ app.get(`/books/*`, async (request, response) => {
7083
7182
  try {
7084
7183
  if (collection === null) {
7085
7184
  response.status(500).send('No collection nor books available');
@@ -7131,26 +7230,10 @@ function startRemoteServer(options) {
7131
7230
  };
7132
7231
  }
7133
7232
  }
7134
- /**
7135
- * @swagger
7136
- * /executions:
7137
- * get:
7138
- * summary: List all executions
7139
- * description: Returns a list of all running execution tasks.
7140
- * responses:
7141
- * 200:
7142
- * description: A list of execution tasks.
7143
- * content:
7144
- * application/json:
7145
- * schema:
7146
- * type: array
7147
- * items:
7148
- * type: object
7149
- */
7150
- app.get([`/executions`, `${rootPath}/executions`], async (request, response) => {
7233
+ app.get(`/executions`, async (request, response) => {
7151
7234
  response.send(runningExecutionTasks.map((runningExecutionTask) => exportExecutionTask(runningExecutionTask, false)));
7152
7235
  });
7153
- app.get([`/executions/last`, `${rootPath}/executions/last`], async (request, response) => {
7236
+ app.get(`/executions/last`, async (request, response) => {
7154
7237
  // TODO: [🤬] Filter only for user
7155
7238
  if (runningExecutionTasks.length === 0) {
7156
7239
  response.status(404).send('No execution tasks found');
@@ -7159,7 +7242,7 @@ function startRemoteServer(options) {
7159
7242
  const lastExecutionTask = runningExecutionTasks[runningExecutionTasks.length - 1];
7160
7243
  response.send(exportExecutionTask(lastExecutionTask, true));
7161
7244
  });
7162
- app.get([`/executions/:taskId`, `${rootPath}/executions/:taskId`], async (request, response) => {
7245
+ app.get(`/executions/:taskId`, async (request, response) => {
7163
7246
  const { taskId } = request.params;
7164
7247
  // TODO: [🤬] Filter only for user
7165
7248
  const executionTask = runningExecutionTasks.find((executionTask) => executionTask.taskId === taskId);
@@ -7171,36 +7254,7 @@ function startRemoteServer(options) {
7171
7254
  }
7172
7255
  response.send(exportExecutionTask(executionTask, true));
7173
7256
  });
7174
- /**
7175
- * @swagger
7176
- * /executions/new:
7177
- * post:
7178
- * summary: Start a new execution
7179
- * description: Starts a new execution task for a given pipeline.
7180
- * requestBody:
7181
- * required: true
7182
- * content:
7183
- * application/json:
7184
- * schema:
7185
- * type: object
7186
- * properties:
7187
- * pipelineUrl:
7188
- * type: string
7189
- * inputParameters:
7190
- * type: object
7191
- * identification:
7192
- * type: object
7193
- * responses:
7194
- * 200:
7195
- * description: The newly created execution task.
7196
- * content:
7197
- * application/json:
7198
- * schema:
7199
- * type: object
7200
- * 400:
7201
- * description: Invalid input.
7202
- */
7203
- app.post([`/executions/new`, `${rootPath}/executions/new`], async (request, response) => {
7257
+ app.post(`/executions/new`, async (request, response) => {
7204
7258
  try {
7205
7259
  const { inputParameters, identification /* <- [🤬] */ } = request.body;
7206
7260
  const pipelineUrl = request.body.pipelineUrl || request.body.book;
@@ -7249,11 +7303,12 @@ function startRemoteServer(options) {
7249
7303
  });
7250
7304
  const httpServer = http.createServer(app);
7251
7305
  const server = new Server(httpServer, {
7252
- path: socketioPath,
7253
- transports: [/*'websocket', <- TODO: [🌬] Make websocket transport work */ 'polling'],
7306
+ path: '/socket.io',
7307
+ transports: ['polling', 'websocket' /*, <- TODO: [🌬] Allow to pass `transports`, add 'webtransport' */],
7254
7308
  cors: {
7255
7309
  origin: '*',
7256
7310
  methods: ['GET', 'POST'],
7311
+ // <- TODO: [🌡] Allow to pass
7257
7312
  },
7258
7313
  });
7259
7314
  server.on('connection', (socket) => {
@@ -7398,7 +7453,7 @@ function startRemoteServer(options) {
7398
7453
  };
7399
7454
  }
7400
7455
  /**
7401
- * TODO: !! Add CORS and security - probbably via `helmet`
7456
+ * TODO: [🌡] Add CORS and security - probbably via `helmet`
7402
7457
  * TODO: Split this file into multiple functions - handler for each request
7403
7458
  * TODO: Maybe use `$exportJson`
7404
7459
  * TODO: [🧠][🛍] Maybe not `isAnonymous: boolean` BUT `mode: 'ANONYMOUS'|'COLLECTION'`