@kapeta/local-cluster-service 0.71.2 → 0.71.4

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,18 @@
1
+ ## [0.71.4](https://github.com/kapetacom/local-cluster-service/compare/v0.71.3...v0.71.4) (2024-09-19)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * Making implementing APIs from faster ([33f4f1c](https://github.com/kapetacom/local-cluster-service/commit/33f4f1c071eb6c248e4912bfceffc820496c6edd))
7
+
8
+ ## [0.71.3](https://github.com/kapetacom/local-cluster-service/compare/v0.71.2...v0.71.3) (2024-09-18)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * Let client know the new reset url ([efabbaa](https://github.com/kapetacom/local-cluster-service/commit/efabbaa4ce9aaf38cc98d6b31383d09d03ad0e9d))
14
+ * Reset page can redirect ([7efbc06](https://github.com/kapetacom/local-cluster-service/commit/7efbc06710226c4edba277749e0a8909fc010219))
15
+
1
16
  ## [0.71.2](https://github.com/kapetacom/local-cluster-service/compare/v0.71.1...v0.71.2) (2024-09-18)
2
17
 
3
18
 
@@ -29,11 +29,33 @@ class UIServer {
29
29
  async start() {
30
30
  const app = (0, express_1.default)();
31
31
  app.get('/_reset', (req, res) => {
32
+ /**
33
+ * Reset page clears local storage and session storage. If a redirect path is provided,
34
+ * it will redirect to that path.
35
+ */
32
36
  res.send(`
33
- <script>
34
- window.localStorage.clear();
35
- window.sessionStorage.clear();
36
- </script>`);
37
+ <html><head>
38
+ <script>
39
+ window.localStorage.clear();
40
+ window.sessionStorage.clear();
41
+
42
+ function isValidURL(url) {
43
+ try {
44
+ const parsedURL = new URL(url, window.location.origin);
45
+ return ['http:', 'https:'].includes(parsedURL.protocol);
46
+ } catch (e) {
47
+ return false;
48
+ }
49
+ }
50
+
51
+ const params = new URLSearchParams(window.location.search);
52
+ const redirect_path = params.get('redirect_path');
53
+
54
+ if (redirect_path && isValidURL(redirect_path)) {
55
+ window.location.href = redirect_path;
56
+ }
57
+ </script>
58
+ </head><body></body></html>`);
37
59
  });
38
60
  // Make it possible to serve static assets
39
61
  app.use(express_1.default.static((0, path_1.join)((0, page_utils_1.getSystemBaseDir)(this.systemId), 'public'), { fallthrough: true }));
@@ -66,7 +66,7 @@ router.post('/ui/serve/:systemId', async (req, res) => {
66
66
  if (!svr.isRunning()) {
67
67
  await UI_SERVERS[systemId].start();
68
68
  }
69
- res.status(200).send({ status: 'running', url: svr.getUrl() });
69
+ res.status(200).send({ status: 'running', url: svr.getUrl(), resetUrl: svr.resolveUrlFromPath('/_reset') });
70
70
  });
71
71
  router.post('/ui/create-system/:handle/:systemId', async (req, res) => {
72
72
  const systemId = req.params.systemId;
@@ -76,17 +76,22 @@ router.post('/ui/create-system/:handle/:systemId', async (req, res) => {
76
76
  res.set('Access-Control-Expose-Headers', stormClient_1.ConversationIdHeader);
77
77
  res.set(stormClient_1.ConversationIdHeader, systemId);
78
78
  sendEvent(res, (0, event_parser_1.createPhaseStartEvent)(events_1.StormEventPhaseType.IMPLEMENT_APIS));
79
- await (0, utils_1.copyDirectory)(srcDir, destDir, async (fileName, content) => {
80
- const result = await stormClient_1.stormClient.implementAPIClients({
81
- content: content,
82
- fileName: fileName,
83
- });
84
- return result;
79
+ const pagesFromDisk = (0, utils_1.readFilesAndContent)(srcDir);
80
+ const pagesWithImplementation = await stormClient_1.stormClient.replaceMockWithAPICall({
81
+ pages: pagesFromDisk,
82
+ });
83
+ await (0, utils_1.copyDirectory)(srcDir, destDir, (fileName, content) => {
84
+ // find the page from result1 and write the content to the file
85
+ const page = pagesWithImplementation.find((p) => p.filename === fileName);
86
+ return page ? page.content : content;
85
87
  });
86
88
  sendEvent(res, (0, event_parser_1.createPhaseEndEvent)(events_1.StormEventPhaseType.IMPLEMENT_APIS));
87
89
  sendEvent(res, (0, event_parser_1.createPhaseStartEvent)(events_1.StormEventPhaseType.COMPOSE_SYSTEM_PROMPT));
88
- const pages = (0, utils_1.readPages)(destDir);
89
- const prompt = await stormClient_1.stormClient.generatePrompt(pages);
90
+ // get the content of the pages
91
+ const pageContents = pagesWithImplementation.map((page) => {
92
+ return page.content;
93
+ });
94
+ const prompt = await stormClient_1.stormClient.generatePrompt(pageContents);
90
95
  sendEvent(res, (0, event_parser_1.createPhaseEndEvent)(events_1.StormEventPhaseType.COMPOSE_SYSTEM_PROMPT));
91
96
  req.query.systemId = systemId;
92
97
  const promptRequest = {
@@ -1,5 +1,5 @@
1
1
  /// <reference types="node" />
2
- import { ConversationItem, ImplementAPIClientsRequest, StormFileImplementationPrompt, StormStream, StormUIImplementationPrompt, StormUIListPrompt } from './stream';
2
+ import { ConversationItem, ImplementAPIClients, StormFileImplementationPrompt, StormStream, StormUIImplementationPrompt, StormUIListPrompt } from './stream';
3
3
  import { Page, StormEventPageUrl } from './events';
4
4
  export declare const STORM_ID = "storm";
5
5
  export declare const ConversationIdHeader = "Conversation-Id";
@@ -70,7 +70,7 @@ declare class StormClient {
70
70
  getVoteUIPage(topic: string, conversationId: string, mainConversationId?: string): Promise<{
71
71
  vote: -1 | 0 | 1;
72
72
  }>;
73
- implementAPIClients(prompt: ImplementAPIClientsRequest): Promise<string>;
73
+ replaceMockWithAPICall(prompt: ImplementAPIClients): Promise<Page[]>;
74
74
  generatePrompt(pages: string[]): Promise<string>;
75
75
  classifyUIReferences(prompt: string, conversationId?: string): Promise<StormStream>;
76
76
  editPages(prompt: UIPageEditPrompt, conversationId?: string): Promise<StormStream>;
@@ -133,16 +133,13 @@ class StormClient {
133
133
  const response = await fetch(options.url, options);
134
134
  return response.json();
135
135
  }
136
- async implementAPIClients(prompt) {
137
- const u = `${this._baseUrl}/v2/ui/implement-api-clients`;
136
+ async replaceMockWithAPICall(prompt) {
137
+ const u = `${this._baseUrl}/v2/ui/implement-api-clients-all`;
138
138
  const response = await fetch(u, {
139
139
  method: 'POST',
140
- body: JSON.stringify({
141
- fileName: prompt.fileName,
142
- content: prompt.content,
143
- }),
140
+ body: JSON.stringify(prompt.pages),
144
141
  });
145
- const data = await response.text();
142
+ const data = await response.json();
146
143
  return data;
147
144
  }
148
145
  async generatePrompt(pages) {
@@ -72,7 +72,10 @@ export interface StormUIListPrompt {
72
72
  blockName: string;
73
73
  prompt: string;
74
74
  }
75
- export interface ImplementAPIClientsRequest {
75
+ export interface ImplementAPIClients {
76
+ pages: Page[];
77
+ }
78
+ export interface Page {
76
79
  fileName: string;
77
80
  content: string;
78
81
  }
@@ -1,5 +1,6 @@
1
- export declare function copyDirectory(src: string, dest: string, modifyHtml: (fileName: string, content: string) => Promise<string>): Promise<void>;
2
- export declare function readPages(directoryPath: string): string[];
1
+ import { Page } from './stream';
2
+ export declare function copyDirectory(src: string, dest: string, modifyHtml: (fileName: string, content: string) => string): Promise<void>;
3
+ export declare function readFilesAndContent(directoryPath: string): Page[];
3
4
  export declare function createFuture<T = void>(): {
4
5
  promise: Promise<T>;
5
6
  resolve: (value: T | PromiseLike<T>) => void;
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.createFuture = exports.readPages = exports.copyDirectory = void 0;
6
+ exports.createFuture = exports.readFilesAndContent = exports.copyDirectory = void 0;
7
7
  /**
8
8
  * Copyright 2023 Kapeta Inc.
9
9
  * SPDX-License-Identifier: BUSL-1.1
@@ -22,33 +22,33 @@ async function copyDirectory(src, dest, modifyHtml) {
22
22
  else if (entry.isFile()) {
23
23
  let content = await fs_extra_1.default.promises.readFile(srcPath, 'utf-8');
24
24
  if (path_1.default.extname(srcPath) === '.html') {
25
- content = await modifyHtml(srcPath, content);
25
+ content = modifyHtml(srcPath, content);
26
26
  }
27
27
  await fs_extra_1.default.promises.writeFile(destPath, content, 'utf-8');
28
28
  }
29
29
  }
30
30
  }
31
31
  exports.copyDirectory = copyDirectory;
32
- function readPages(directoryPath) {
32
+ function readFilesAndContent(directoryPath) {
33
33
  const htmlFiles = [];
34
34
  function traverseDirectory(currentPath) {
35
35
  const files = fs_extra_1.default.readdirSync(currentPath);
36
36
  for (const file of files) {
37
- const filePath = path_1.default.join(currentPath, file);
38
- const stats = fs_extra_1.default.statSync(filePath);
37
+ const fileName = path_1.default.join(currentPath, file);
38
+ const stats = fs_extra_1.default.statSync(fileName);
39
39
  if (stats.isDirectory()) {
40
- traverseDirectory(filePath);
40
+ traverseDirectory(fileName);
41
41
  }
42
- else if (stats.isFile() && path_1.default.extname(filePath) === '.html') {
43
- const content = fs_extra_1.default.readFileSync(filePath, 'utf8');
44
- htmlFiles.push(content);
42
+ else if (stats.isFile() && path_1.default.extname(fileName) === '.html') {
43
+ const content = fs_extra_1.default.readFileSync(fileName, 'utf8');
44
+ htmlFiles.push({ fileName, content });
45
45
  }
46
46
  }
47
47
  }
48
48
  traverseDirectory(directoryPath);
49
49
  return htmlFiles;
50
50
  }
51
- exports.readPages = readPages;
51
+ exports.readFilesAndContent = readFilesAndContent;
52
52
  function createFuture() {
53
53
  let resolve = () => { };
54
54
  let reject = () => { };
@@ -29,11 +29,33 @@ class UIServer {
29
29
  async start() {
30
30
  const app = (0, express_1.default)();
31
31
  app.get('/_reset', (req, res) => {
32
+ /**
33
+ * Reset page clears local storage and session storage. If a redirect path is provided,
34
+ * it will redirect to that path.
35
+ */
32
36
  res.send(`
33
- <script>
34
- window.localStorage.clear();
35
- window.sessionStorage.clear();
36
- </script>`);
37
+ <html><head>
38
+ <script>
39
+ window.localStorage.clear();
40
+ window.sessionStorage.clear();
41
+
42
+ function isValidURL(url) {
43
+ try {
44
+ const parsedURL = new URL(url, window.location.origin);
45
+ return ['http:', 'https:'].includes(parsedURL.protocol);
46
+ } catch (e) {
47
+ return false;
48
+ }
49
+ }
50
+
51
+ const params = new URLSearchParams(window.location.search);
52
+ const redirect_path = params.get('redirect_path');
53
+
54
+ if (redirect_path && isValidURL(redirect_path)) {
55
+ window.location.href = redirect_path;
56
+ }
57
+ </script>
58
+ </head><body></body></html>`);
37
59
  });
38
60
  // Make it possible to serve static assets
39
61
  app.use(express_1.default.static((0, path_1.join)((0, page_utils_1.getSystemBaseDir)(this.systemId), 'public'), { fallthrough: true }));
@@ -66,7 +66,7 @@ router.post('/ui/serve/:systemId', async (req, res) => {
66
66
  if (!svr.isRunning()) {
67
67
  await UI_SERVERS[systemId].start();
68
68
  }
69
- res.status(200).send({ status: 'running', url: svr.getUrl() });
69
+ res.status(200).send({ status: 'running', url: svr.getUrl(), resetUrl: svr.resolveUrlFromPath('/_reset') });
70
70
  });
71
71
  router.post('/ui/create-system/:handle/:systemId', async (req, res) => {
72
72
  const systemId = req.params.systemId;
@@ -76,17 +76,22 @@ router.post('/ui/create-system/:handle/:systemId', async (req, res) => {
76
76
  res.set('Access-Control-Expose-Headers', stormClient_1.ConversationIdHeader);
77
77
  res.set(stormClient_1.ConversationIdHeader, systemId);
78
78
  sendEvent(res, (0, event_parser_1.createPhaseStartEvent)(events_1.StormEventPhaseType.IMPLEMENT_APIS));
79
- await (0, utils_1.copyDirectory)(srcDir, destDir, async (fileName, content) => {
80
- const result = await stormClient_1.stormClient.implementAPIClients({
81
- content: content,
82
- fileName: fileName,
83
- });
84
- return result;
79
+ const pagesFromDisk = (0, utils_1.readFilesAndContent)(srcDir);
80
+ const pagesWithImplementation = await stormClient_1.stormClient.replaceMockWithAPICall({
81
+ pages: pagesFromDisk,
82
+ });
83
+ await (0, utils_1.copyDirectory)(srcDir, destDir, (fileName, content) => {
84
+ // find the page from result1 and write the content to the file
85
+ const page = pagesWithImplementation.find((p) => p.filename === fileName);
86
+ return page ? page.content : content;
85
87
  });
86
88
  sendEvent(res, (0, event_parser_1.createPhaseEndEvent)(events_1.StormEventPhaseType.IMPLEMENT_APIS));
87
89
  sendEvent(res, (0, event_parser_1.createPhaseStartEvent)(events_1.StormEventPhaseType.COMPOSE_SYSTEM_PROMPT));
88
- const pages = (0, utils_1.readPages)(destDir);
89
- const prompt = await stormClient_1.stormClient.generatePrompt(pages);
90
+ // get the content of the pages
91
+ const pageContents = pagesWithImplementation.map((page) => {
92
+ return page.content;
93
+ });
94
+ const prompt = await stormClient_1.stormClient.generatePrompt(pageContents);
90
95
  sendEvent(res, (0, event_parser_1.createPhaseEndEvent)(events_1.StormEventPhaseType.COMPOSE_SYSTEM_PROMPT));
91
96
  req.query.systemId = systemId;
92
97
  const promptRequest = {
@@ -1,5 +1,5 @@
1
1
  /// <reference types="node" />
2
- import { ConversationItem, ImplementAPIClientsRequest, StormFileImplementationPrompt, StormStream, StormUIImplementationPrompt, StormUIListPrompt } from './stream';
2
+ import { ConversationItem, ImplementAPIClients, StormFileImplementationPrompt, StormStream, StormUIImplementationPrompt, StormUIListPrompt } from './stream';
3
3
  import { Page, StormEventPageUrl } from './events';
4
4
  export declare const STORM_ID = "storm";
5
5
  export declare const ConversationIdHeader = "Conversation-Id";
@@ -70,7 +70,7 @@ declare class StormClient {
70
70
  getVoteUIPage(topic: string, conversationId: string, mainConversationId?: string): Promise<{
71
71
  vote: -1 | 0 | 1;
72
72
  }>;
73
- implementAPIClients(prompt: ImplementAPIClientsRequest): Promise<string>;
73
+ replaceMockWithAPICall(prompt: ImplementAPIClients): Promise<Page[]>;
74
74
  generatePrompt(pages: string[]): Promise<string>;
75
75
  classifyUIReferences(prompt: string, conversationId?: string): Promise<StormStream>;
76
76
  editPages(prompt: UIPageEditPrompt, conversationId?: string): Promise<StormStream>;
@@ -133,16 +133,13 @@ class StormClient {
133
133
  const response = await fetch(options.url, options);
134
134
  return response.json();
135
135
  }
136
- async implementAPIClients(prompt) {
137
- const u = `${this._baseUrl}/v2/ui/implement-api-clients`;
136
+ async replaceMockWithAPICall(prompt) {
137
+ const u = `${this._baseUrl}/v2/ui/implement-api-clients-all`;
138
138
  const response = await fetch(u, {
139
139
  method: 'POST',
140
- body: JSON.stringify({
141
- fileName: prompt.fileName,
142
- content: prompt.content,
143
- }),
140
+ body: JSON.stringify(prompt.pages),
144
141
  });
145
- const data = await response.text();
142
+ const data = await response.json();
146
143
  return data;
147
144
  }
148
145
  async generatePrompt(pages) {
@@ -72,7 +72,10 @@ export interface StormUIListPrompt {
72
72
  blockName: string;
73
73
  prompt: string;
74
74
  }
75
- export interface ImplementAPIClientsRequest {
75
+ export interface ImplementAPIClients {
76
+ pages: Page[];
77
+ }
78
+ export interface Page {
76
79
  fileName: string;
77
80
  content: string;
78
81
  }
@@ -1,5 +1,6 @@
1
- export declare function copyDirectory(src: string, dest: string, modifyHtml: (fileName: string, content: string) => Promise<string>): Promise<void>;
2
- export declare function readPages(directoryPath: string): string[];
1
+ import { Page } from './stream';
2
+ export declare function copyDirectory(src: string, dest: string, modifyHtml: (fileName: string, content: string) => string): Promise<void>;
3
+ export declare function readFilesAndContent(directoryPath: string): Page[];
3
4
  export declare function createFuture<T = void>(): {
4
5
  promise: Promise<T>;
5
6
  resolve: (value: T | PromiseLike<T>) => void;
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.createFuture = exports.readPages = exports.copyDirectory = void 0;
6
+ exports.createFuture = exports.readFilesAndContent = exports.copyDirectory = void 0;
7
7
  /**
8
8
  * Copyright 2023 Kapeta Inc.
9
9
  * SPDX-License-Identifier: BUSL-1.1
@@ -22,33 +22,33 @@ async function copyDirectory(src, dest, modifyHtml) {
22
22
  else if (entry.isFile()) {
23
23
  let content = await fs_extra_1.default.promises.readFile(srcPath, 'utf-8');
24
24
  if (path_1.default.extname(srcPath) === '.html') {
25
- content = await modifyHtml(srcPath, content);
25
+ content = modifyHtml(srcPath, content);
26
26
  }
27
27
  await fs_extra_1.default.promises.writeFile(destPath, content, 'utf-8');
28
28
  }
29
29
  }
30
30
  }
31
31
  exports.copyDirectory = copyDirectory;
32
- function readPages(directoryPath) {
32
+ function readFilesAndContent(directoryPath) {
33
33
  const htmlFiles = [];
34
34
  function traverseDirectory(currentPath) {
35
35
  const files = fs_extra_1.default.readdirSync(currentPath);
36
36
  for (const file of files) {
37
- const filePath = path_1.default.join(currentPath, file);
38
- const stats = fs_extra_1.default.statSync(filePath);
37
+ const fileName = path_1.default.join(currentPath, file);
38
+ const stats = fs_extra_1.default.statSync(fileName);
39
39
  if (stats.isDirectory()) {
40
- traverseDirectory(filePath);
40
+ traverseDirectory(fileName);
41
41
  }
42
- else if (stats.isFile() && path_1.default.extname(filePath) === '.html') {
43
- const content = fs_extra_1.default.readFileSync(filePath, 'utf8');
44
- htmlFiles.push(content);
42
+ else if (stats.isFile() && path_1.default.extname(fileName) === '.html') {
43
+ const content = fs_extra_1.default.readFileSync(fileName, 'utf8');
44
+ htmlFiles.push({ fileName, content });
45
45
  }
46
46
  }
47
47
  }
48
48
  traverseDirectory(directoryPath);
49
49
  return htmlFiles;
50
50
  }
51
- exports.readPages = readPages;
51
+ exports.readFilesAndContent = readFilesAndContent;
52
52
  function createFuture() {
53
53
  let resolve = () => { };
54
54
  let reject = () => { };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kapeta/local-cluster-service",
3
- "version": "0.71.2",
3
+ "version": "0.71.4",
4
4
  "description": "Manages configuration, ports and service discovery for locally running Kapeta systems",
5
5
  "type": "commonjs",
6
6
  "exports": {
@@ -30,12 +30,34 @@ export class UIServer {
30
30
  public async start() {
31
31
  const app = express();
32
32
  app.get('/_reset', (req: Request, res: Response) => {
33
+ /**
34
+ * Reset page clears local storage and session storage. If a redirect path is provided,
35
+ * it will redirect to that path.
36
+ */
33
37
  res.send(
34
38
  `
35
- <script>
36
- window.localStorage.clear();
37
- window.sessionStorage.clear();
38
- </script>`
39
+ <html><head>
40
+ <script>
41
+ window.localStorage.clear();
42
+ window.sessionStorage.clear();
43
+
44
+ function isValidURL(url) {
45
+ try {
46
+ const parsedURL = new URL(url, window.location.origin);
47
+ return ['http:', 'https:'].includes(parsedURL.protocol);
48
+ } catch (e) {
49
+ return false;
50
+ }
51
+ }
52
+
53
+ const params = new URLSearchParams(window.location.search);
54
+ const redirect_path = params.get('redirect_path');
55
+
56
+ if (redirect_path && isValidURL(redirect_path)) {
57
+ window.location.href = redirect_path;
58
+ }
59
+ </script>
60
+ </head><body></body></html>`
39
61
  );
40
62
  });
41
63
 
@@ -37,8 +37,6 @@ import uuid from 'node-uuid';
37
37
  import {
38
38
  getSystemBaseDir,
39
39
  getSystemBaseImplDir,
40
- readPageFromDisk,
41
- resolveReadPath,
42
40
  SystemIdHeader,
43
41
  writeAssetToDisk,
44
42
  writePageToDisk,
@@ -46,7 +44,7 @@ import {
46
44
  import { UIServer } from './UIServer';
47
45
  import { randomUUID } from 'crypto';
48
46
  import { ImagePrompt, PageQueue } from './PageGenerator';
49
- import { copyDirectory, createFuture, readPages } from './utils';
47
+ import { copyDirectory, createFuture, readFilesAndContent } from './utils';
50
48
 
51
49
  const UI_SERVERS: { [key: string]: UIServer } = {};
52
50
  const router = Router();
@@ -97,7 +95,7 @@ router.post('/ui/serve/:systemId', async (req: KapetaBodyRequest, res: Response)
97
95
  await UI_SERVERS[systemId].start();
98
96
  }
99
97
 
100
- res.status(200).send({ status: 'running', url: svr.getUrl() });
98
+ res.status(200).send({ status: 'running', url: svr.getUrl(), resetUrl: svr.resolveUrlFromPath('/_reset') });
101
99
  });
102
100
 
103
101
  router.post('/ui/create-system/:handle/:systemId', async (req: KapetaBodyRequest, res: Response) => {
@@ -111,20 +109,28 @@ router.post('/ui/create-system/:handle/:systemId', async (req: KapetaBodyRequest
111
109
 
112
110
  sendEvent(res, createPhaseStartEvent(StormEventPhaseType.IMPLEMENT_APIS));
113
111
 
114
- await copyDirectory(srcDir, destDir, async (fileName, content) => {
115
- const result = await stormClient.implementAPIClients({
116
- content: content,
117
- fileName: fileName,
118
- });
119
- return result;
112
+ const pagesFromDisk = readFilesAndContent(srcDir);
113
+ const pagesWithImplementation = await stormClient.replaceMockWithAPICall({
114
+ pages: pagesFromDisk,
115
+ },
116
+ );
117
+ await copyDirectory(srcDir, destDir, (fileName, content) => {
118
+ // find the page from result1 and write the content to the file
119
+ const page = pagesWithImplementation.find((p) => p.filename === fileName);
120
+ return page ? page.content : content;
120
121
  });
121
122
 
123
+
122
124
  sendEvent(res, createPhaseEndEvent(StormEventPhaseType.IMPLEMENT_APIS));
123
125
 
124
126
  sendEvent(res, createPhaseStartEvent(StormEventPhaseType.COMPOSE_SYSTEM_PROMPT));
125
127
 
126
- const pages = readPages(destDir);
127
- const prompt = await stormClient.generatePrompt(pages);
128
+ // get the content of the pages
129
+ const pageContents = pagesWithImplementation.map((page) => {
130
+ return page.content
131
+ })
132
+
133
+ const prompt = await stormClient.generatePrompt(pageContents);
128
134
 
129
135
  sendEvent(res, createPhaseEndEvent(StormEventPhaseType.COMPOSE_SYSTEM_PROMPT));
130
136
 
@@ -134,7 +140,6 @@ router.post('/ui/create-system/:handle/:systemId', async (req: KapetaBodyRequest
134
140
  skipImprovement: true,
135
141
  };
136
142
  req.stringBody = JSON.stringify(promptRequest);
137
-
138
143
  await handleAll(req, res);
139
144
  });
140
145
 
@@ -8,7 +8,7 @@ import readLine from 'node:readline/promises';
8
8
  import { Readable } from 'node:stream';
9
9
  import {
10
10
  ConversationItem,
11
- ImplementAPIClientsRequest,
11
+ ImplementAPIClients,
12
12
  StormContextRequest,
13
13
  StormFileImplementationPrompt,
14
14
  StormStream,
@@ -238,16 +238,13 @@ class StormClient {
238
238
  return response.json() as Promise<{ vote: -1 | 0 | 1 }>;
239
239
  }
240
240
 
241
- public async implementAPIClients(prompt: ImplementAPIClientsRequest) {
242
- const u = `${this._baseUrl}/v2/ui/implement-api-clients`;
241
+ public async replaceMockWithAPICall(prompt: ImplementAPIClients) {
242
+ const u = `${this._baseUrl}/v2/ui/implement-api-clients-all`;
243
243
  const response = await fetch(u, {
244
244
  method: 'POST',
245
- body: JSON.stringify({
246
- fileName: prompt.fileName,
247
- content: prompt.content,
248
- }),
245
+ body: JSON.stringify(prompt.pages),
249
246
  });
250
- const data = await response.text();
247
+ const data = await response.json() as Page[];
251
248
  return data;
252
249
  }
253
250
 
@@ -143,7 +143,11 @@ export interface StormUIListPrompt {
143
143
  prompt: string;
144
144
  }
145
145
 
146
- export interface ImplementAPIClientsRequest {
146
+ export interface ImplementAPIClients {
147
+ pages: Page[];
148
+ }
149
+
150
+ export interface Page {
147
151
  fileName: string;
148
152
  content: string
149
153
  }
@@ -4,11 +4,12 @@
4
4
  */
5
5
  import FS from 'fs-extra';
6
6
  import Path from 'path';
7
+ import { Page } from './stream';
7
8
 
8
9
  export async function copyDirectory(
9
10
  src: string,
10
11
  dest: string,
11
- modifyHtml: (fileName: string, content: string) => Promise<string>
12
+ modifyHtml: (fileName: string, content: string) => string
12
13
  ): Promise<void> {
13
14
  await FS.promises.mkdir(dest, { recursive: true });
14
15
  const entries = await FS.promises.readdir(src, { withFileTypes: true });
@@ -23,7 +24,7 @@ export async function copyDirectory(
23
24
  let content = await FS.promises.readFile(srcPath, 'utf-8');
24
25
 
25
26
  if (Path.extname(srcPath) === '.html') {
26
- content = await modifyHtml(srcPath, content);
27
+ content = modifyHtml(srcPath, content);
27
28
  }
28
29
 
29
30
  await FS.promises.writeFile(destPath, content, 'utf-8');
@@ -31,21 +32,19 @@ export async function copyDirectory(
31
32
  }
32
33
  }
33
34
 
34
- export function readPages(directoryPath: string): string[] {
35
- const htmlFiles: string[] = [];
35
+ export function readFilesAndContent(directoryPath: string): Page[] {
36
+ const htmlFiles:Page[] = [];
36
37
 
37
38
  function traverseDirectory(currentPath: string) {
38
39
  const files = FS.readdirSync(currentPath);
39
-
40
40
  for (const file of files) {
41
- const filePath = Path.join(currentPath, file);
42
- const stats = FS.statSync(filePath);
43
-
41
+ const fileName = Path.join(currentPath, file);
42
+ const stats = FS.statSync(fileName);
44
43
  if (stats.isDirectory()) {
45
- traverseDirectory(filePath);
46
- } else if (stats.isFile() && Path.extname(filePath) === '.html') {
47
- const content = FS.readFileSync(filePath, 'utf8');
48
- htmlFiles.push(content);
44
+ traverseDirectory(fileName);
45
+ } else if (stats.isFile() && Path.extname(fileName) === '.html') {
46
+ const content = FS.readFileSync(fileName, 'utf8');
47
+ htmlFiles.push({fileName, content});
49
48
  }
50
49
  }
51
50
  }