@kapeta/local-cluster-service 0.64.1 → 0.64.3

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/CHANGELOG.md CHANGED
@@ -1,3 +1,17 @@
1
+ ## [0.64.3](https://github.com/kapetacom/local-cluster-service/compare/v0.64.2...v0.64.3) (2024-08-23)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * Handle new prompt payload format in edit ([#223](https://github.com/kapetacom/local-cluster-service/issues/223)) ([bf06e8a](https://github.com/kapetacom/local-cluster-service/commit/bf06e8a9d82833fcaf076c254e46cc94f945a23c))
7
+
8
+ ## [0.64.2](https://github.com/kapetacom/local-cluster-service/compare/v0.64.1...v0.64.2) (2024-08-22)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * handle port detection on multiple interfaces ([#222](https://github.com/kapetacom/local-cluster-service/issues/222)) ([6635cc2](https://github.com/kapetacom/local-cluster-service/commit/6635cc207355b2083edbb380f0ba83227c6a16e1))
14
+
1
15
  ## [0.64.1](https://github.com/kapetacom/local-cluster-service/compare/v0.64.0...v0.64.1) (2024-08-21)
2
16
 
3
17
 
@@ -16,7 +16,7 @@ declare class ClusterService {
16
16
  * Gets next available port
17
17
  */
18
18
  getNextAvailablePort(startPort?: number): Promise<number>;
19
- _checkIfPortIsUsed(port: number, host?: string): Promise<unknown>;
19
+ private resolveWithAvailablePort;
20
20
  /**
21
21
  * The port of this local cluster service itself
22
22
  */
@@ -42,10 +42,13 @@ class ClusterService {
42
42
  }
43
43
  async _findClusterServicePort() {
44
44
  for (; this._port <= 65535; this._port++) {
45
- const isUsed = await this._checkIfPortIsUsed(this._port);
46
- if (!isUsed) {
45
+ try {
46
+ await this.resolveWithAvailablePort(this._port);
47
47
  return;
48
48
  }
49
+ catch (e) {
50
+ // try again
51
+ }
49
52
  }
50
53
  throw new Error('No available ports');
51
54
  }
@@ -54,28 +57,33 @@ class ClusterService {
54
57
  */
55
58
  async getNextAvailablePort(startPort = -1) {
56
59
  for (let nextPort = startPort > 0 ? startPort : this._currentPort; nextPort <= 65535; nextPort++) {
57
- if (this._reservedPorts.indexOf(startPort) > -1) {
60
+ if (this._reservedPorts.indexOf(nextPort) > -1) {
58
61
  continue;
59
62
  }
60
- const isUsed = await this._checkIfPortIsUsed(nextPort);
61
- if (!isUsed) {
63
+ try {
64
+ // Try both IPv4 and IPv6 addresses
65
+ await this.resolveWithAvailablePort(nextPort);
66
+ await this.resolveWithAvailablePort(nextPort, '0.0.0.0');
62
67
  // Save the state if we're looking for a system port for the cluster itself
63
68
  if (startPort <= 0) {
64
69
  this._currentPort = nextPort;
65
70
  }
66
71
  return nextPort;
67
72
  }
73
+ catch (e) {
74
+ // try again }
75
+ }
68
76
  }
69
77
  throw new Error('No available ports');
70
78
  }
71
- _checkIfPortIsUsed(port, host = this._host) {
79
+ async resolveWithAvailablePort(port, host = this._host) {
72
80
  return new Promise((resolve, reject) => {
73
81
  const server = net_1.default.createServer();
74
82
  server.unref();
75
- server.on('error', () => resolve(true));
76
- server.listen({ port, host }, () => {
83
+ server.on('error', reject);
84
+ server.listen({ port, host }, (...args) => {
77
85
  server.close(() => {
78
- resolve(false);
86
+ resolve(port);
79
87
  });
80
88
  });
81
89
  });
@@ -1,13 +1,5 @@
1
- /// <reference types="node" />
2
- import { Server } from 'http';
3
1
  import { StormEventPage } from './events';
4
- declare module 'express-serve-static-core' {
5
- interface Application {
6
- listen(port: number, callback?: (err?: Error) => void): Server;
7
- }
8
- }
9
2
  export declare class UIServer {
10
- private readonly express;
11
3
  private readonly systemId;
12
4
  private port;
13
5
  private server;
@@ -11,34 +11,31 @@ exports.UIServer = void 0;
11
11
  const express_1 = __importDefault(require("express"));
12
12
  const page_utils_1 = require("./page-utils");
13
13
  const clusterService_1 = require("../clusterService");
14
+ const http_1 = require("http");
14
15
  class UIServer {
15
- express;
16
16
  systemId;
17
17
  port = 50000;
18
18
  server;
19
19
  constructor(systemId) {
20
20
  this.systemId = systemId;
21
- this.express = (0, express_1.default)();
22
21
  }
23
22
  async start() {
24
- this.port = await clusterService_1.clusterService.getNextAvailablePort(this.port);
25
- this.express.get('/_reset', (req, res) => {
23
+ const app = (0, express_1.default)();
24
+ app.get('/_reset', (req, res) => {
26
25
  res.send(`
27
26
  <script>
28
27
  window.localStorage.clear();
29
28
  window.sessionStorage.clear();
30
29
  </script>`);
31
30
  });
32
- this.express.all('/*', (req, res) => {
31
+ app.all('/*', (req, res) => {
33
32
  (0, page_utils_1.readPageFromDisk)(this.systemId, req.params[0], req.method, res);
34
33
  });
34
+ this.port = await clusterService_1.clusterService.getNextAvailablePort(this.port);
35
35
  return new Promise((resolve, reject) => {
36
- this.server = this.express.listen(this.port, (err) => {
37
- if (err) {
38
- console.error('Failed to start UI server', err);
39
- reject(err);
40
- return;
41
- }
36
+ this.server = (0, http_1.createServer)(app);
37
+ this.server.on('error', reject);
38
+ this.server.listen(this.port, () => {
42
39
  console.log(`UI Server started on port ${this.port}`);
43
40
  resolve();
44
41
  });
@@ -321,7 +321,9 @@ router.post('/ui/edit', async (req, res) => {
321
321
  })
322
322
  .filter((page) => !!page);
323
323
  const editStream = await stormClient_1.stormClient.editPages({
324
- ...aiRequest.prompt,
324
+ prompt: aiRequest.prompt.prompt.prompt,
325
+ blockDescription: aiRequest.prompt.blockDescription,
326
+ planDescription: aiRequest.prompt.planDescription,
325
327
  pages,
326
328
  }, conversationId);
327
329
  onRequestAborted(req, res, () => {
@@ -36,7 +36,7 @@ export interface UIPageEditRequest {
36
36
  planDescription: string;
37
37
  blockDescription: string;
38
38
  pages: StormEventPageUrl['payload'][];
39
- prompt: string;
39
+ prompt: BasePromptRequest;
40
40
  }
41
41
  export interface BasePromptRequest {
42
42
  prompt: string;
@@ -16,7 +16,7 @@ declare class ClusterService {
16
16
  * Gets next available port
17
17
  */
18
18
  getNextAvailablePort(startPort?: number): Promise<number>;
19
- _checkIfPortIsUsed(port: number, host?: string): Promise<unknown>;
19
+ private resolveWithAvailablePort;
20
20
  /**
21
21
  * The port of this local cluster service itself
22
22
  */
@@ -42,10 +42,13 @@ class ClusterService {
42
42
  }
43
43
  async _findClusterServicePort() {
44
44
  for (; this._port <= 65535; this._port++) {
45
- const isUsed = await this._checkIfPortIsUsed(this._port);
46
- if (!isUsed) {
45
+ try {
46
+ await this.resolveWithAvailablePort(this._port);
47
47
  return;
48
48
  }
49
+ catch (e) {
50
+ // try again
51
+ }
49
52
  }
50
53
  throw new Error('No available ports');
51
54
  }
@@ -54,28 +57,33 @@ class ClusterService {
54
57
  */
55
58
  async getNextAvailablePort(startPort = -1) {
56
59
  for (let nextPort = startPort > 0 ? startPort : this._currentPort; nextPort <= 65535; nextPort++) {
57
- if (this._reservedPorts.indexOf(startPort) > -1) {
60
+ if (this._reservedPorts.indexOf(nextPort) > -1) {
58
61
  continue;
59
62
  }
60
- const isUsed = await this._checkIfPortIsUsed(nextPort);
61
- if (!isUsed) {
63
+ try {
64
+ // Try both IPv4 and IPv6 addresses
65
+ await this.resolveWithAvailablePort(nextPort);
66
+ await this.resolveWithAvailablePort(nextPort, '0.0.0.0');
62
67
  // Save the state if we're looking for a system port for the cluster itself
63
68
  if (startPort <= 0) {
64
69
  this._currentPort = nextPort;
65
70
  }
66
71
  return nextPort;
67
72
  }
73
+ catch (e) {
74
+ // try again }
75
+ }
68
76
  }
69
77
  throw new Error('No available ports');
70
78
  }
71
- _checkIfPortIsUsed(port, host = this._host) {
79
+ async resolveWithAvailablePort(port, host = this._host) {
72
80
  return new Promise((resolve, reject) => {
73
81
  const server = net_1.default.createServer();
74
82
  server.unref();
75
- server.on('error', () => resolve(true));
76
- server.listen({ port, host }, () => {
83
+ server.on('error', reject);
84
+ server.listen({ port, host }, (...args) => {
77
85
  server.close(() => {
78
- resolve(false);
86
+ resolve(port);
79
87
  });
80
88
  });
81
89
  });
@@ -1,13 +1,5 @@
1
- /// <reference types="node" />
2
- import { Server } from 'http';
3
1
  import { StormEventPage } from './events';
4
- declare module 'express-serve-static-core' {
5
- interface Application {
6
- listen(port: number, callback?: (err?: Error) => void): Server;
7
- }
8
- }
9
2
  export declare class UIServer {
10
- private readonly express;
11
3
  private readonly systemId;
12
4
  private port;
13
5
  private server;
@@ -11,34 +11,31 @@ exports.UIServer = void 0;
11
11
  const express_1 = __importDefault(require("express"));
12
12
  const page_utils_1 = require("./page-utils");
13
13
  const clusterService_1 = require("../clusterService");
14
+ const http_1 = require("http");
14
15
  class UIServer {
15
- express;
16
16
  systemId;
17
17
  port = 50000;
18
18
  server;
19
19
  constructor(systemId) {
20
20
  this.systemId = systemId;
21
- this.express = (0, express_1.default)();
22
21
  }
23
22
  async start() {
24
- this.port = await clusterService_1.clusterService.getNextAvailablePort(this.port);
25
- this.express.get('/_reset', (req, res) => {
23
+ const app = (0, express_1.default)();
24
+ app.get('/_reset', (req, res) => {
26
25
  res.send(`
27
26
  <script>
28
27
  window.localStorage.clear();
29
28
  window.sessionStorage.clear();
30
29
  </script>`);
31
30
  });
32
- this.express.all('/*', (req, res) => {
31
+ app.all('/*', (req, res) => {
33
32
  (0, page_utils_1.readPageFromDisk)(this.systemId, req.params[0], req.method, res);
34
33
  });
34
+ this.port = await clusterService_1.clusterService.getNextAvailablePort(this.port);
35
35
  return new Promise((resolve, reject) => {
36
- this.server = this.express.listen(this.port, (err) => {
37
- if (err) {
38
- console.error('Failed to start UI server', err);
39
- reject(err);
40
- return;
41
- }
36
+ this.server = (0, http_1.createServer)(app);
37
+ this.server.on('error', reject);
38
+ this.server.listen(this.port, () => {
42
39
  console.log(`UI Server started on port ${this.port}`);
43
40
  resolve();
44
41
  });
@@ -321,7 +321,9 @@ router.post('/ui/edit', async (req, res) => {
321
321
  })
322
322
  .filter((page) => !!page);
323
323
  const editStream = await stormClient_1.stormClient.editPages({
324
- ...aiRequest.prompt,
324
+ prompt: aiRequest.prompt.prompt.prompt,
325
+ blockDescription: aiRequest.prompt.blockDescription,
326
+ planDescription: aiRequest.prompt.planDescription,
325
327
  pages,
326
328
  }, conversationId);
327
329
  onRequestAborted(req, res, () => {
@@ -36,7 +36,7 @@ export interface UIPageEditRequest {
36
36
  planDescription: string;
37
37
  blockDescription: string;
38
38
  pages: StormEventPageUrl['payload'][];
39
- prompt: string;
39
+ prompt: BasePromptRequest;
40
40
  }
41
41
  export interface BasePromptRequest {
42
42
  prompt: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kapeta/local-cluster-service",
3
- "version": "0.64.1",
3
+ "version": "0.64.3",
4
4
  "description": "Manages configuration, ports and service discovery for locally running Kapeta systems",
5
5
  "type": "commonjs",
6
6
  "exports": {
@@ -45,9 +45,11 @@ class ClusterService {
45
45
 
46
46
  async _findClusterServicePort() {
47
47
  for (; this._port <= 65535; this._port++) {
48
- const isUsed = await this._checkIfPortIsUsed(this._port);
49
- if (!isUsed) {
48
+ try {
49
+ await this.resolveWithAvailablePort(this._port);
50
50
  return;
51
+ } catch (e) {
52
+ // try again
51
53
  }
52
54
  }
53
55
  throw new Error('No available ports');
@@ -58,31 +60,35 @@ class ClusterService {
58
60
  */
59
61
  public async getNextAvailablePort(startPort: number = -1) {
60
62
  for (let nextPort = startPort > 0 ? startPort : this._currentPort; nextPort <= 65535; nextPort++) {
61
- if (this._reservedPorts.indexOf(startPort) > -1) {
63
+ if (this._reservedPorts.indexOf(nextPort) > -1) {
62
64
  continue;
63
65
  }
64
66
 
65
- const isUsed = await this._checkIfPortIsUsed(nextPort);
66
- if (!isUsed) {
67
+ try {
68
+ // Try both IPv4 and IPv6 addresses
69
+ await this.resolveWithAvailablePort(nextPort);
70
+ await this.resolveWithAvailablePort(nextPort, '0.0.0.0');
67
71
  // Save the state if we're looking for a system port for the cluster itself
68
72
  if (startPort <= 0) {
69
73
  this._currentPort = nextPort;
70
74
  }
71
75
  return nextPort;
76
+ } catch (e) {
77
+ // try again }
72
78
  }
73
79
  }
74
80
  throw new Error('No available ports');
75
81
  }
76
82
 
77
- _checkIfPortIsUsed(port: number, host: string = this._host) {
83
+ private async resolveWithAvailablePort(port: number, host: string = this._host) {
78
84
  return new Promise((resolve, reject) => {
79
85
  const server = net.createServer();
80
86
  server.unref();
81
- server.on('error', () => resolve(true));
87
+ server.on('error', reject);
82
88
 
83
- server.listen({ port, host }, () => {
89
+ server.listen({ port, host }, (...args) => {
84
90
  server.close(() => {
85
- resolve(false);
91
+ resolve(port);
86
92
  });
87
93
  });
88
94
  });
@@ -5,20 +5,10 @@
5
5
  import express, { Express, Request, Response } from 'express';
6
6
  import { readPageFromDisk } from './page-utils';
7
7
  import { clusterService } from '../clusterService';
8
- import { Server } from 'http';
8
+ import { createServer, Server } from 'http';
9
9
  import { StormEventPage } from './events';
10
10
 
11
- declare module 'express-serve-static-core' {
12
- interface Application {
13
- // Adds error callback support
14
- // From the docs:
15
- // All the forms of Node’s http.Server.listen() method are in fact actually supported.
16
- listen(port: number, callback?: (err?: Error) => void): Server;
17
- }
18
- }
19
-
20
11
  export class UIServer {
21
- private readonly express: Express;
22
12
  private readonly systemId: string;
23
13
 
24
14
  private port: number = 50000;
@@ -26,13 +16,11 @@ export class UIServer {
26
16
 
27
17
  constructor(systemId: string) {
28
18
  this.systemId = systemId;
29
- this.express = express();
30
19
  }
31
20
 
32
21
  public async start() {
33
- this.port = await clusterService.getNextAvailablePort(this.port);
34
-
35
- this.express.get('/_reset', (req: Request, res: Response) => {
22
+ const app = express();
23
+ app.get('/_reset', (req: Request, res: Response) => {
36
24
  res.send(
37
25
  `
38
26
  <script>
@@ -42,17 +30,16 @@ export class UIServer {
42
30
  );
43
31
  });
44
32
 
45
- this.express.all('/*', (req: Request, res: Response) => {
33
+ app.all('/*', (req: Request, res: Response) => {
46
34
  readPageFromDisk(this.systemId, req.params[0], req.method, res);
47
35
  });
48
36
 
37
+ this.port = await clusterService.getNextAvailablePort(this.port);
49
38
  return new Promise<void>((resolve, reject) => {
50
- this.server = this.express.listen(this.port, (err) => {
51
- if (err) {
52
- console.error('Failed to start UI server', err);
53
- reject(err);
54
- return;
55
- }
39
+ this.server = createServer(app);
40
+ this.server.on('error', reject);
41
+
42
+ this.server.listen(this.port, () => {
56
43
  console.log(`UI Server started on port ${this.port}`);
57
44
  resolve();
58
45
  });
@@ -405,7 +405,9 @@ router.post('/ui/edit', async (req: KapetaBodyRequest, res: Response) => {
405
405
 
406
406
  const editStream = await stormClient.editPages(
407
407
  {
408
- ...aiRequest.prompt,
408
+ prompt: aiRequest.prompt.prompt.prompt,
409
+ blockDescription: aiRequest.prompt.blockDescription,
410
+ planDescription: aiRequest.prompt.planDescription,
409
411
  pages,
410
412
  },
411
413
  conversationId
@@ -59,7 +59,7 @@ export interface UIPageEditRequest {
59
59
  planDescription: string;
60
60
  blockDescription: string;
61
61
  pages: StormEventPageUrl['payload'][];
62
- prompt: string;
62
+ prompt: BasePromptRequest;
63
63
  }
64
64
 
65
65
  export interface BasePromptRequest {