@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 +15 -0
- package/dist/cjs/src/storm/UIServer.js +26 -4
- package/dist/cjs/src/storm/routes.js +14 -9
- package/dist/cjs/src/storm/stormClient.d.ts +2 -2
- package/dist/cjs/src/storm/stormClient.js +4 -7
- package/dist/cjs/src/storm/stream.d.ts +4 -1
- package/dist/cjs/src/storm/utils.d.ts +3 -2
- package/dist/cjs/src/storm/utils.js +10 -10
- package/dist/esm/src/storm/UIServer.js +26 -4
- package/dist/esm/src/storm/routes.js +14 -9
- package/dist/esm/src/storm/stormClient.d.ts +2 -2
- package/dist/esm/src/storm/stormClient.js +4 -7
- package/dist/esm/src/storm/stream.d.ts +4 -1
- package/dist/esm/src/storm/utils.d.ts +3 -2
- package/dist/esm/src/storm/utils.js +10 -10
- package/package.json +1 -1
- package/src/storm/UIServer.ts +26 -4
- package/src/storm/routes.ts +18 -13
- package/src/storm/stormClient.ts +5 -8
- package/src/storm/stream.ts +5 -1
- package/src/storm/utils.ts +11 -12
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
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
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
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
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
|
-
|
89
|
-
const
|
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,
|
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
|
-
|
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
|
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.
|
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
|
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
|
-
|
2
|
-
export declare function
|
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.
|
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 =
|
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
|
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
|
38
|
-
const stats = fs_extra_1.default.statSync(
|
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(
|
40
|
+
traverseDirectory(fileName);
|
41
41
|
}
|
42
|
-
else if (stats.isFile() && path_1.default.extname(
|
43
|
-
const content = fs_extra_1.default.readFileSync(
|
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.
|
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
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
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
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
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
|
-
|
89
|
-
const
|
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,
|
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
|
-
|
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
|
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.
|
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
|
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
|
-
|
2
|
-
export declare function
|
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.
|
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 =
|
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
|
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
|
38
|
-
const stats = fs_extra_1.default.statSync(
|
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(
|
40
|
+
traverseDirectory(fileName);
|
41
41
|
}
|
42
|
-
else if (stats.isFile() && path_1.default.extname(
|
43
|
-
const content = fs_extra_1.default.readFileSync(
|
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.
|
51
|
+
exports.readFilesAndContent = readFilesAndContent;
|
52
52
|
function createFuture() {
|
53
53
|
let resolve = () => { };
|
54
54
|
let reject = () => { };
|
package/package.json
CHANGED
package/src/storm/UIServer.ts
CHANGED
@@ -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
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
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
|
|
package/src/storm/routes.ts
CHANGED
@@ -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,
|
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
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
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
|
-
|
127
|
-
const
|
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
|
|
package/src/storm/stormClient.ts
CHANGED
@@ -8,7 +8,7 @@ import readLine from 'node:readline/promises';
|
|
8
8
|
import { Readable } from 'node:stream';
|
9
9
|
import {
|
10
10
|
ConversationItem,
|
11
|
-
|
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
|
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.
|
247
|
+
const data = await response.json() as Page[];
|
251
248
|
return data;
|
252
249
|
}
|
253
250
|
|
package/src/storm/stream.ts
CHANGED
@@ -143,7 +143,11 @@ export interface StormUIListPrompt {
|
|
143
143
|
prompt: string;
|
144
144
|
}
|
145
145
|
|
146
|
-
export interface
|
146
|
+
export interface ImplementAPIClients {
|
147
|
+
pages: Page[];
|
148
|
+
}
|
149
|
+
|
150
|
+
export interface Page {
|
147
151
|
fileName: string;
|
148
152
|
content: string
|
149
153
|
}
|
package/src/storm/utils.ts
CHANGED
@@ -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) =>
|
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 =
|
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
|
35
|
-
const htmlFiles:
|
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
|
42
|
-
const stats = FS.statSync(
|
43
|
-
|
41
|
+
const fileName = Path.join(currentPath, file);
|
42
|
+
const stats = FS.statSync(fileName);
|
44
43
|
if (stats.isDirectory()) {
|
45
|
-
traverseDirectory(
|
46
|
-
} else if (stats.isFile() && Path.extname(
|
47
|
-
const content = FS.readFileSync(
|
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
|
}
|