@promptbook/cli 0.89.0-21 β†’ 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
@@ -23,7 +23,7 @@ import moment from 'moment';
23
23
  import express from 'express';
24
24
  import http from 'http';
25
25
  import { Server } from 'socket.io';
26
- import swaggerJsdoc from 'swagger-jsdoc';
26
+ import * as OpenApiValidator from 'express-openapi-validator';
27
27
  import swaggerUi from 'swagger-ui-express';
28
28
  import Anthropic from '@anthropic-ai/sdk';
29
29
  import { OpenAIClient, AzureKeyCredential } from '@azure/openai';
@@ -46,7 +46,7 @@ const BOOK_LANGUAGE_VERSION = '1.0.0';
46
46
  * @generated
47
47
  * @see https://github.com/webgptorg/promptbook
48
48
  */
49
- const PROMPTBOOK_ENGINE_VERSION = '0.89.0-21';
49
+ const PROMPTBOOK_ENGINE_VERSION = '0.89.0-28';
50
50
  /**
51
51
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
52
52
  * Note: [πŸ’ž] Ignore a discrepancy between file name and entity name
@@ -64,10 +64,12 @@ const REMOTE_SERVER_URLS = [
64
64
  owner: 'AI Web, LLC <legal@ptbk.io> (https://www.ptbk.io/)',
65
65
  isAnonymousModeAllowed: true,
66
66
  urls: [
67
- 'https://s5.ptbk.io/promptbook',
67
+ 'https://promptbook.s5.ptbk.io/',
68
68
  // Note: Servers 1-4 are not running
69
69
  ],
70
70
  },
71
+ /*
72
+ Note: Working on older version of Promptbook and not supported anymore
71
73
  {
72
74
  title: 'Pavol Promptbook Server',
73
75
  description: `Personal server of Pavol HejnΓ½ with simple testing server, DO NOT USE IT FOR PRODUCTION`,
@@ -75,6 +77,7 @@ const REMOTE_SERVER_URLS = [
75
77
  isAnonymousModeAllowed: true,
76
78
  urls: ['https://api.pavolhejny.com/promptbook'],
77
79
  },
80
+ */
78
81
  ];
79
82
  /**
80
83
  * Note: [πŸ’ž] Ignore a discrepancy between file name and entity name
@@ -2429,11 +2432,25 @@ function deserializeError(error) {
2429
2432
  */
2430
2433
  async function createRemoteClient(options) {
2431
2434
  const { remoteServerUrl } = options;
2432
- console.log('!!! Connecting to socket.io server', remoteServerUrl, {
2433
- retries: CONNECTION_RETRIES_LIMIT,
2434
- timeout: CONNECTION_TIMEOUT_MS,
2435
- path: '/socket.io',
2436
- });
2435
+ if (!isValidUrl(remoteServerUrl)) {
2436
+ throw new Error(`Invalid \`remoteServerUrl\`: "${remoteServerUrl}"`);
2437
+ }
2438
+ const remoteServerUrlParsed = new URL(remoteServerUrl);
2439
+ if (remoteServerUrlParsed.pathname !== '/' && remoteServerUrlParsed.pathname !== '') {
2440
+ remoteServerUrlParsed.pathname = '/';
2441
+ throw new Error(spaceTrim((block) => `
2442
+ Remote server requires root url \`/\`
2443
+
2444
+ You have provided \`remoteServerUrl\`:
2445
+ ${block(remoteServerUrl)}
2446
+
2447
+ But something like this is expected:
2448
+ ${block(remoteServerUrlParsed.href)}
2449
+
2450
+ Note: If you need to run multiple services on the same server, use 3rd or 4th degree subdomain
2451
+
2452
+ `));
2453
+ }
2437
2454
  return new Promise((resolve, reject) => {
2438
2455
  const socket = io(remoteServerUrl, {
2439
2456
  retries: CONNECTION_RETRIES_LIMIT,
@@ -13091,6 +13108,198 @@ function $initializeRunCommand(program) {
13091
13108
  * TODO: [πŸ–‡] What about symlinks? Maybe flag --follow-symlinks
13092
13109
  */
13093
13110
 
13111
+ // TODO: !!! List running services from REMOTE_SERVER_URLS
13112
+ // TODO: !!! Import directly from YML
13113
+ /**
13114
+ * @private !!!! Decide how to expose this
13115
+ */
13116
+ const openapiJson = {
13117
+ openapi: '3.0.0',
13118
+ info: {
13119
+ title: 'Promptbook Remote Server API (!!! From TS)',
13120
+ version: '1.0.0',
13121
+ description: 'API documentation for the Promptbook Remote Server',
13122
+ },
13123
+ paths: {
13124
+ '/': {
13125
+ get: {
13126
+ summary: 'Get server details',
13127
+ description: 'Returns details about the Promptbook server.',
13128
+ responses: {
13129
+ '200': {
13130
+ description: 'Server details in markdown format.',
13131
+ },
13132
+ },
13133
+ },
13134
+ },
13135
+ '/login': {
13136
+ post: {
13137
+ summary: 'Login to the server',
13138
+ description: 'Login to the server and get identification.',
13139
+ requestBody: {
13140
+ required: true,
13141
+ content: {
13142
+ 'application/json': {
13143
+ schema: {
13144
+ type: 'object',
13145
+ properties: {
13146
+ username: {
13147
+ type: 'string',
13148
+ },
13149
+ password: {
13150
+ type: 'string',
13151
+ },
13152
+ appId: {
13153
+ type: 'string',
13154
+ },
13155
+ },
13156
+ },
13157
+ },
13158
+ },
13159
+ },
13160
+ responses: {
13161
+ '200': {
13162
+ description: 'Successful login',
13163
+ content: {
13164
+ 'application/json': {
13165
+ schema: {
13166
+ type: 'object',
13167
+ properties: {
13168
+ identification: {
13169
+ type: 'object',
13170
+ },
13171
+ },
13172
+ },
13173
+ },
13174
+ },
13175
+ },
13176
+ },
13177
+ },
13178
+ },
13179
+ '/books': {
13180
+ get: {
13181
+ summary: 'List all books',
13182
+ description: 'Returns a list of all available books in the collection.',
13183
+ responses: {
13184
+ '200': {
13185
+ description: 'A list of books.',
13186
+ content: {
13187
+ 'application/json': {
13188
+ schema: {
13189
+ type: 'array',
13190
+ items: {
13191
+ type: 'string',
13192
+ },
13193
+ },
13194
+ },
13195
+ },
13196
+ },
13197
+ },
13198
+ },
13199
+ },
13200
+ '/books/{bookId}': {
13201
+ get: {
13202
+ summary: 'Get book content',
13203
+ description: 'Returns the content of a specific book.',
13204
+ parameters: [
13205
+ {
13206
+ in: 'path',
13207
+ name: 'bookId',
13208
+ required: true,
13209
+ schema: {
13210
+ type: 'string',
13211
+ },
13212
+ description: 'The ID of the book to retrieve.',
13213
+ },
13214
+ ],
13215
+ responses: {
13216
+ '200': {
13217
+ description: 'The content of the book.',
13218
+ content: {
13219
+ 'text/markdown': {
13220
+ schema: {
13221
+ type: 'string',
13222
+ },
13223
+ },
13224
+ },
13225
+ },
13226
+ '404': {
13227
+ description: 'Book not found.',
13228
+ },
13229
+ },
13230
+ },
13231
+ },
13232
+ '/executions': {
13233
+ get: {
13234
+ summary: 'List all executions',
13235
+ description: 'Returns a list of all running execution tasks.',
13236
+ responses: {
13237
+ '200': {
13238
+ description: 'A list of execution tasks.',
13239
+ content: {
13240
+ 'application/json': {
13241
+ schema: {
13242
+ type: 'array',
13243
+ items: {
13244
+ type: 'object',
13245
+ },
13246
+ },
13247
+ },
13248
+ },
13249
+ },
13250
+ },
13251
+ },
13252
+ },
13253
+ '/executions/new': {
13254
+ post: {
13255
+ summary: 'Start a new execution',
13256
+ description: 'Starts a new execution task for a given pipeline.',
13257
+ requestBody: {
13258
+ required: true,
13259
+ content: {
13260
+ 'application/json': {
13261
+ schema: {
13262
+ type: 'object',
13263
+ properties: {
13264
+ pipelineUrl: {
13265
+ type: 'string',
13266
+ },
13267
+ inputParameters: {
13268
+ type: 'object',
13269
+ },
13270
+ identification: {
13271
+ type: 'object',
13272
+ },
13273
+ },
13274
+ },
13275
+ },
13276
+ },
13277
+ },
13278
+ responses: {
13279
+ '200': {
13280
+ description: 'The newly created execution task.',
13281
+ content: {
13282
+ 'application/json': {
13283
+ schema: {
13284
+ type: 'object',
13285
+ },
13286
+ },
13287
+ },
13288
+ },
13289
+ '400': {
13290
+ description: 'Invalid input.',
13291
+ },
13292
+ },
13293
+ },
13294
+ },
13295
+ },
13296
+ components: {},
13297
+ tags: [],
13298
+ };
13299
+ /**
13300
+ * Note: [πŸ’ž] Ignore a discrepancy between file name and entity name
13301
+ */
13302
+
13094
13303
  /**
13095
13304
  * Remote server is a proxy server that uses its execution tools internally and exposes the executor interface externally.
13096
13305
  *
@@ -13165,43 +13374,34 @@ function startRemoteServer(options) {
13165
13374
  response.setHeader('X-Powered-By', 'Promptbook engine');
13166
13375
  next();
13167
13376
  });
13168
- const swaggerOptions = {
13169
- definition: {
13170
- openapi: '3.0.0',
13171
- info: {
13172
- title: 'Promptbook Remote Server API',
13173
- version: '1.0.0',
13174
- description: 'API documentation for the Promptbook Remote Server',
13175
- },
13176
- /*
13177
- TODO:
13178
- servers: [
13179
- {
13180
- url: `http://localhost:${port}${rootPath}`,
13181
- // <- TODO: Pass some public URLs here
13182
- },
13183
- ],
13184
- */
13377
+ // TODO: !!! Expose openapiJson to consumer and also allow to add new routes
13378
+ app.use(OpenApiValidator.middleware({
13379
+ apiSpec: openapiJson,
13380
+ // TODO: !!! Adjust
13381
+ ignorePaths(...args) {
13382
+ console.warn(`!!! Ignoring paths`, ...args);
13383
+ return true;
13185
13384
  },
13186
- apis: ['./src/remote-server/**/*.ts'], // Adjust path as needed
13187
- };
13188
- const swaggerSpec = swaggerJsdoc(swaggerOptions);
13189
- const rootPath = ''; // <- TODO: !!!! Remove after merging into feature/elysia+openai+swagger-2
13190
- app.use([`/api-docs`, `${rootPath}/api-docs`], swaggerUi.serve, swaggerUi.setup(swaggerSpec));
13385
+ // TODO: !!! Validate both
13386
+ validateRequests: false,
13387
+ validateResponses: false, // false by default
13388
+ }));
13389
+ app.use([`/api-docs`, `/swagger`], swaggerUi.serve, swaggerUi.setup(openapiJson, {
13390
+ // customCss: '.swagger-ui .topbar { display: none }',
13391
+ // customSiteTitle: 'BRJ API',
13392
+ // customfavIcon: 'https://brj.app/favicon.ico',
13393
+ }));
13394
+ app.get(`/openapi`, (request, response) => {
13395
+ response.json(openapiJson);
13396
+ });
13397
+ // TODO: !!! Remove:
13398
+ app.get(`/xxx`, (request, response) => {
13399
+ response.json(openapiJson);
13400
+ });
13191
13401
  const runningExecutionTasks = [];
13192
13402
  // <- TODO: [🀬] Identify the users
13193
13403
  // TODO: [🧠] Do here some garbage collection of finished tasks
13194
- /**
13195
- * @swagger
13196
- * /:
13197
- * get:
13198
- * summary: Get server details
13199
- * description: Returns details about the Promptbook server.
13200
- * responses:
13201
- * 200:
13202
- * description: Server details in markdown format.
13203
- */
13204
- app.get(['/', rootPath], async (request, response) => {
13404
+ app.get('/', async (request, response) => {
13205
13405
  var _a;
13206
13406
  if ((_a = request.url) === null || _a === void 0 ? void 0 : _a.includes('socket.io')) {
13207
13407
  return;
@@ -13220,7 +13420,6 @@ function startRemoteServer(options) {
13220
13420
  ## Details
13221
13421
 
13222
13422
  **Server port:** ${port}
13223
- **Server root path:** ${rootPath}
13224
13423
  **Startup date:** ${startupDate.toISOString()}
13225
13424
  **Anonymouse mode:** ${isAnonymousModeAllowed ? 'enabled' : 'disabled'}
13226
13425
  **Application mode:** ${isApplicationModeAllowed ? 'enabled' : 'disabled'}
@@ -13259,38 +13458,7 @@ function startRemoteServer(options) {
13259
13458
  https://github.com/webgptorg/promptbook
13260
13459
  `));
13261
13460
  });
13262
- /**
13263
- * @swagger
13264
- *
13265
- * /login:
13266
- * post:
13267
- * summary: Login to the server
13268
- * description: Login to the server and get identification.
13269
- * requestBody:
13270
- * required: true
13271
- * content:
13272
- * application/json:
13273
- * schema:
13274
- * type: object
13275
- * properties:
13276
- * username:
13277
- * type: string
13278
- * password:
13279
- * type: string
13280
- * appId:
13281
- * type: string
13282
- * responses:
13283
- * 200:
13284
- * description: Successful login
13285
- * content:
13286
- * application/json:
13287
- * schema:
13288
- * type: object
13289
- * properties:
13290
- * identification:
13291
- * type: object
13292
- */
13293
- app.post([`/login`, `${rootPath}/login`], async (request, response) => {
13461
+ app.post(`/login`, async (request, response) => {
13294
13462
  if (!isApplicationModeAllowed || login === null) {
13295
13463
  response.status(400).send('Application mode is not allowed');
13296
13464
  return;
@@ -13330,23 +13498,7 @@ function startRemoteServer(options) {
13330
13498
  response.status(400).send({ error: serializeError(error) });
13331
13499
  }
13332
13500
  });
13333
- /**
13334
- * @swagger
13335
- * /books:
13336
- * get:
13337
- * summary: List all books
13338
- * description: Returns a list of all available books in the collection.
13339
- * responses:
13340
- * 200:
13341
- * description: A list of books.
13342
- * content:
13343
- * application/json:
13344
- * schema:
13345
- * type: array
13346
- * items:
13347
- * type: string
13348
- */
13349
- app.get([`/books`, `${rootPath}/books`], async (request, response) => {
13501
+ app.get(`/books`, async (request, response) => {
13350
13502
  if (collection === null) {
13351
13503
  response.status(500).send('No collection available');
13352
13504
  return;
@@ -13356,30 +13508,7 @@ function startRemoteServer(options) {
13356
13508
  response.send(pipelines);
13357
13509
  });
13358
13510
  // TODO: [🧠] Is it secure / good idea to expose source codes of hosted books
13359
- /**
13360
- * @swagger
13361
- * /books/{bookId}:
13362
- * get:
13363
- * summary: Get book content
13364
- * description: Returns the content of a specific book.
13365
- * parameters:
13366
- * - in: path
13367
- * name: bookId
13368
- * required: true
13369
- * schema:
13370
- * type: string
13371
- * description: The ID of the book to retrieve.
13372
- * responses:
13373
- * 200:
13374
- * description: The content of the book.
13375
- * content:
13376
- * text/markdown:
13377
- * schema:
13378
- * type: string
13379
- * 404:
13380
- * description: Book not found.
13381
- */
13382
- app.get([`/books/*`, `${rootPath}/books/*`], async (request, response) => {
13511
+ app.get(`/books/*`, async (request, response) => {
13383
13512
  try {
13384
13513
  if (collection === null) {
13385
13514
  response.status(500).send('No collection nor books available');
@@ -13431,26 +13560,10 @@ function startRemoteServer(options) {
13431
13560
  };
13432
13561
  }
13433
13562
  }
13434
- /**
13435
- * @swagger
13436
- * /executions:
13437
- * get:
13438
- * summary: List all executions
13439
- * description: Returns a list of all running execution tasks.
13440
- * responses:
13441
- * 200:
13442
- * description: A list of execution tasks.
13443
- * content:
13444
- * application/json:
13445
- * schema:
13446
- * type: array
13447
- * items:
13448
- * type: object
13449
- */
13450
- app.get([`/executions`, `${rootPath}/executions`], async (request, response) => {
13563
+ app.get(`/executions`, async (request, response) => {
13451
13564
  response.send(runningExecutionTasks.map((runningExecutionTask) => exportExecutionTask(runningExecutionTask, false)));
13452
13565
  });
13453
- app.get([`/executions/last`, `${rootPath}/executions/last`], async (request, response) => {
13566
+ app.get(`/executions/last`, async (request, response) => {
13454
13567
  // TODO: [🀬] Filter only for user
13455
13568
  if (runningExecutionTasks.length === 0) {
13456
13569
  response.status(404).send('No execution tasks found');
@@ -13459,7 +13572,7 @@ function startRemoteServer(options) {
13459
13572
  const lastExecutionTask = runningExecutionTasks[runningExecutionTasks.length - 1];
13460
13573
  response.send(exportExecutionTask(lastExecutionTask, true));
13461
13574
  });
13462
- app.get([`/executions/:taskId`, `${rootPath}/executions/:taskId`], async (request, response) => {
13575
+ app.get(`/executions/:taskId`, async (request, response) => {
13463
13576
  const { taskId } = request.params;
13464
13577
  // TODO: [🀬] Filter only for user
13465
13578
  const executionTask = runningExecutionTasks.find((executionTask) => executionTask.taskId === taskId);
@@ -13471,36 +13584,7 @@ function startRemoteServer(options) {
13471
13584
  }
13472
13585
  response.send(exportExecutionTask(executionTask, true));
13473
13586
  });
13474
- /**
13475
- * @swagger
13476
- * /executions/new:
13477
- * post:
13478
- * summary: Start a new execution
13479
- * description: Starts a new execution task for a given pipeline.
13480
- * requestBody:
13481
- * required: true
13482
- * content:
13483
- * application/json:
13484
- * schema:
13485
- * type: object
13486
- * properties:
13487
- * pipelineUrl:
13488
- * type: string
13489
- * inputParameters:
13490
- * type: object
13491
- * identification:
13492
- * type: object
13493
- * responses:
13494
- * 200:
13495
- * description: The newly created execution task.
13496
- * content:
13497
- * application/json:
13498
- * schema:
13499
- * type: object
13500
- * 400:
13501
- * description: Invalid input.
13502
- */
13503
- app.post([`/executions/new`, `${rootPath}/executions/new`], async (request, response) => {
13587
+ app.post(`/executions/new`, async (request, response) => {
13504
13588
  try {
13505
13589
  const { inputParameters, identification /* <- [🀬] */ } = request.body;
13506
13590
  const pipelineUrl = request.body.pipelineUrl || request.body.book;