@kapeta/local-cluster-service 0.73.0 → 0.74.1
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 +14 -0
- package/dist/cjs/src/storm/PageGenerator.js +6 -3
- package/dist/cjs/src/storm/codegen.js +11 -7
- package/dist/cjs/src/storm/events.d.ts +9 -1
- package/dist/cjs/src/storm/routes.js +20 -11
- package/dist/cjs/src/storm/stormClient.d.ts +4 -4
- package/dist/cjs/src/storm/stormClient.js +13 -3
- package/dist/cjs/src/storm/stream.d.ts +2 -0
- package/dist/cjs/src/stormService.d.ts +3 -2
- package/dist/cjs/src/stormService.js +44 -21
- package/dist/esm/src/storm/PageGenerator.js +6 -3
- package/dist/esm/src/storm/codegen.js +11 -7
- package/dist/esm/src/storm/events.d.ts +9 -1
- package/dist/esm/src/storm/routes.js +20 -11
- package/dist/esm/src/storm/stormClient.d.ts +4 -4
- package/dist/esm/src/storm/stormClient.js +13 -3
- package/dist/esm/src/storm/stream.d.ts +2 -0
- package/dist/esm/src/stormService.d.ts +3 -2
- package/dist/esm/src/stormService.js +44 -21
- package/package.json +1 -1
- package/src/storm/PageGenerator.ts +7 -4
- package/src/storm/codegen.ts +5 -2
- package/src/storm/events.ts +12 -2
- package/src/storm/routes.ts +16 -9
- package/src/storm/stormClient.ts +12 -7
- package/src/storm/stream.ts +2 -0
- package/src/stormService.ts +63 -39
@@ -117,8 +117,10 @@ router.post('/ui/create-system/:handle/:systemId', async (req, res) => {
|
|
117
117
|
res.set(stormClient_1.ConversationIdHeader, systemId);
|
118
118
|
sendEvent(res, (0, event_parser_1.createPhaseStartEvent)(events_1.StormEventPhaseType.IMPLEMENT_APIS));
|
119
119
|
const pagesFromDisk = (0, utils_1.readFilesAndContent)(srcDir);
|
120
|
-
const
|
120
|
+
const client = new stormClient_1.StormClient(systemId);
|
121
|
+
const pagesWithImplementation = await client.replaceMockWithAPICall({
|
121
122
|
pages: pagesFromDisk,
|
123
|
+
systemId: systemId,
|
122
124
|
});
|
123
125
|
await (0, utils_1.copyDirectory)(srcDir, destDir, (fileName, content) => {
|
124
126
|
// find the page from result1 and write the content to the file
|
@@ -131,7 +133,7 @@ router.post('/ui/create-system/:handle/:systemId', async (req, res) => {
|
|
131
133
|
const pageContents = pagesWithImplementation.map((page) => {
|
132
134
|
return page.content;
|
133
135
|
});
|
134
|
-
const prompt = await
|
136
|
+
const prompt = await client.generatePrompt(pageContents);
|
135
137
|
sendEvent(res, (0, event_parser_1.createPhaseEndEvent)(events_1.StormEventPhaseType.COMPOSE_SYSTEM_PROMPT));
|
136
138
|
req.query.systemId = systemId;
|
137
139
|
const promptRequest = {
|
@@ -149,10 +151,12 @@ router.post('/ui/create-system-simple/:handle/:systemId', async (req, res) => {
|
|
149
151
|
//res.set('Access-Control-Expose-Headers', ConversationIdHeader);
|
150
152
|
//res.set(ConversationIdHeader, systemId);
|
151
153
|
//sendEvent(res, createPhaseStartEvent(StormEventPhaseType.IMPLEMENT_APIS));
|
154
|
+
const client = new stormClient_1.StormClient(systemId);
|
152
155
|
try {
|
153
156
|
const pagesFromDisk = (0, utils_1.readFilesAndContent)(srcDir);
|
154
|
-
const pagesWithImplementation = await
|
157
|
+
const pagesWithImplementation = await client.replaceMockWithAPICall({
|
155
158
|
pages: pagesFromDisk,
|
159
|
+
systemId: systemId,
|
156
160
|
});
|
157
161
|
//sendEvent(res, createPhaseEndEvent(StormEventPhaseType.IMPLEMENT_APIS));
|
158
162
|
//sendEvent(res, createPhaseStartEvent(StormEventPhaseType.COMPOSE_SYSTEM));
|
@@ -165,7 +169,7 @@ router.post('/ui/create-system-simple/:handle/:systemId', async (req, res) => {
|
|
165
169
|
}
|
166
170
|
return page;
|
167
171
|
});
|
168
|
-
const systemUrl = await
|
172
|
+
const systemUrl = await client.createSimpleBackend(handle, systemId, { pages: allFiles });
|
169
173
|
//sendEvent(res, {type: 'SYSTEM_READY', created: Math.floor(Date.now() / 1000), reason: 'System Ready', payload: { systemUrl: systemUrl }});
|
170
174
|
//sendEvent(res, createPhaseEndEvent(StormEventPhaseType.COMPOSE_SYSTEM));
|
171
175
|
//sendDone(res);
|
@@ -250,7 +254,8 @@ router.post('/:handle/ui/iterative', async (req, res) => {
|
|
250
254
|
try {
|
251
255
|
const conversationId = req.headers[stormClient_1.ConversationIdHeader.toLowerCase()];
|
252
256
|
const aiRequest = JSON.parse(req.stringBody ?? '{}');
|
253
|
-
const
|
257
|
+
const client = new stormClient_1.StormClient(conversationId); //todo is this correct we are using the landing page getConversationId down below as well
|
258
|
+
const landingPagesStream = await client.createUILandingPages(aiRequest, conversationId);
|
254
259
|
onRequestAborted(req, res, () => {
|
255
260
|
landingPagesStream.abort();
|
256
261
|
});
|
@@ -339,8 +344,9 @@ router.post('/:handle/ui', async (req, res) => {
|
|
339
344
|
try {
|
340
345
|
const outerConversationId = req.headers[stormClient_1.ConversationIdHeader.toLowerCase()] || (0, crypto_1.randomUUID)();
|
341
346
|
const aiRequest = JSON.parse(req.stringBody ?? '{}');
|
347
|
+
const stormClient = new stormClient_1.StormClient(outerConversationId);
|
342
348
|
// Get user journeys
|
343
|
-
const userJourneysStream = await
|
349
|
+
const userJourneysStream = await stormClient.createUIUserJourneys(aiRequest, outerConversationId);
|
344
350
|
onRequestAborted(req, res, () => {
|
345
351
|
userJourneysStream.abort();
|
346
352
|
});
|
@@ -378,7 +384,7 @@ router.post('/:handle/ui', async (req, res) => {
|
|
378
384
|
});
|
379
385
|
let theme = '';
|
380
386
|
try {
|
381
|
-
const themeStream = await
|
387
|
+
const themeStream = await stormClient.createTheme(aiRequest, outerConversationId);
|
382
388
|
onRequestAborted(req, res, () => {
|
383
389
|
themeStream.abort();
|
384
390
|
});
|
@@ -417,7 +423,7 @@ router.post('/:handle/ui', async (req, res) => {
|
|
417
423
|
}
|
418
424
|
await waitForStormStream(userJourneysStream);
|
419
425
|
// Get the UI shells
|
420
|
-
const shellsStream = await
|
426
|
+
const shellsStream = await stormClient.createUIShells({
|
421
427
|
theme: theme || undefined,
|
422
428
|
pages: Object.values(uniqueUserJourneyScreens).map((screen) => ({
|
423
429
|
name: screen.name,
|
@@ -574,7 +580,8 @@ router.post('/ui/vote', async (req, res) => {
|
|
574
580
|
const aiRequest = JSON.parse(req.stringBody ?? '{}');
|
575
581
|
const { topic, vote, mainConversationId } = aiRequest;
|
576
582
|
try {
|
577
|
-
|
583
|
+
const stormClient = new stormClient_1.StormClient(mainConversationId);
|
584
|
+
await stormClient.voteUIPage(topic, conversationId, vote, mainConversationId);
|
578
585
|
}
|
579
586
|
catch (e) {
|
580
587
|
res.status(500).send({ error: e.message });
|
@@ -585,7 +592,8 @@ router.post('/ui/get-vote', async (req, res) => {
|
|
585
592
|
const aiRequest = JSON.parse(req.stringBody ?? '{}');
|
586
593
|
const { topic, mainConversationId } = aiRequest;
|
587
594
|
try {
|
588
|
-
const
|
595
|
+
const stormClient = new stormClient_1.StormClient(mainConversationId);
|
596
|
+
const vote = await stormClient.getVoteUIPage(topic, conversationId, mainConversationId);
|
589
597
|
res.send({ vote });
|
590
598
|
}
|
591
599
|
catch (e) {
|
@@ -609,7 +617,8 @@ async function handleAll(req, res) {
|
|
609
617
|
const eventParser = new event_parser_1.StormEventParser(stormOptions);
|
610
618
|
const conversationId = req.headers[stormClient_1.ConversationIdHeader.toLowerCase()];
|
611
619
|
const aiRequest = JSON.parse(req.stringBody ?? '{}');
|
612
|
-
const
|
620
|
+
const stormClient = new stormClient_1.StormClient(systemId);
|
621
|
+
const metaStream = await stormClient.createMetadata(aiRequest, conversationId);
|
613
622
|
onRequestAborted(req, res, () => {
|
614
623
|
metaStream.abort();
|
615
624
|
});
|
@@ -4,6 +4,7 @@ import { ConversationItem, CreateSimpleBackendRequest, HTMLPage, ImplementAPICli
|
|
4
4
|
import { Page, StormEventPageUrl } from './events';
|
5
5
|
export declare const STORM_ID = "storm";
|
6
6
|
export declare const ConversationIdHeader = "Conversation-Id";
|
7
|
+
export declare const SystemIdHeader = "System-Id";
|
7
8
|
export interface UIShellsPrompt {
|
8
9
|
theme?: string;
|
9
10
|
pages: {
|
@@ -55,9 +56,10 @@ export interface BasePromptRequest {
|
|
55
56
|
prompt: string;
|
56
57
|
skipImprovement?: boolean;
|
57
58
|
}
|
58
|
-
declare class StormClient {
|
59
|
+
export declare class StormClient {
|
59
60
|
private readonly _baseUrl;
|
60
|
-
|
61
|
+
private readonly _systemId;
|
62
|
+
constructor(systemId?: string);
|
61
63
|
private createOptions;
|
62
64
|
private send;
|
63
65
|
createMetadata(prompt: BasePromptRequest, conversationId?: string): Promise<StormStream>;
|
@@ -88,5 +90,3 @@ declare class StormClient {
|
|
88
90
|
downloadSystem(handle: string, conversationId: string): Promise<Buffer>;
|
89
91
|
uploadSystem(handle: string, conversationId: string, buffer: Buffer): Promise<Response>;
|
90
92
|
}
|
91
|
-
export declare const stormClient: StormClient;
|
92
|
-
export {};
|
@@ -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.
|
6
|
+
exports.StormClient = exports.SystemIdHeader = exports.ConversationIdHeader = exports.STORM_ID = void 0;
|
7
7
|
/**
|
8
8
|
* Copyright 2023 Kapeta Inc.
|
9
9
|
* SPDX-License-Identifier: BUSL-1.1
|
@@ -17,10 +17,13 @@ const fetch_retry_1 = __importDefault(require("fetch-retry"));
|
|
17
17
|
const fetchWithRetries = (0, fetch_retry_1.default)(global.fetch, { retries: 5, retryDelay: 10 });
|
18
18
|
exports.STORM_ID = 'storm';
|
19
19
|
exports.ConversationIdHeader = 'Conversation-Id';
|
20
|
+
exports.SystemIdHeader = 'System-Id';
|
20
21
|
class StormClient {
|
21
22
|
_baseUrl;
|
22
|
-
|
23
|
+
_systemId;
|
24
|
+
constructor(systemId) {
|
23
25
|
this._baseUrl = (0, utils_1.getRemoteUrl)('ai-service', 'https://ai.kapeta.com');
|
26
|
+
this._systemId = systemId || "";
|
24
27
|
}
|
25
28
|
async createOptions(path, method, body) {
|
26
29
|
const url = `${this._baseUrl}${path}`;
|
@@ -35,6 +38,9 @@ class StormClient {
|
|
35
38
|
if (body.conversationId) {
|
36
39
|
headers[exports.ConversationIdHeader] = body.conversationId;
|
37
40
|
}
|
41
|
+
if (this._systemId) {
|
42
|
+
headers[exports.SystemIdHeader] = this._systemId;
|
43
|
+
}
|
38
44
|
return {
|
39
45
|
url,
|
40
46
|
method: method,
|
@@ -103,6 +109,7 @@ class StormClient {
|
|
103
109
|
createUIShells(prompt, conversationId) {
|
104
110
|
return this.send('/v2/ui/shells', {
|
105
111
|
prompt: JSON.stringify(prompt),
|
112
|
+
conversationId: conversationId,
|
106
113
|
});
|
107
114
|
}
|
108
115
|
createUILandingPages(prompt, conversationId) {
|
@@ -138,6 +145,9 @@ class StormClient {
|
|
138
145
|
const response = await fetch(u, {
|
139
146
|
method: 'POST',
|
140
147
|
body: JSON.stringify(prompt.pages),
|
148
|
+
headers: {
|
149
|
+
'systemId': prompt.systemId,
|
150
|
+
},
|
141
151
|
});
|
142
152
|
return (await response.json());
|
143
153
|
}
|
@@ -252,4 +262,4 @@ class StormClient {
|
|
252
262
|
return response;
|
253
263
|
}
|
254
264
|
}
|
255
|
-
exports.
|
265
|
+
exports.StormClient = StormClient;
|
@@ -35,6 +35,7 @@ export interface ConversationItem {
|
|
35
35
|
}
|
36
36
|
export interface StormContextRequest<T = string> {
|
37
37
|
conversationId?: string;
|
38
|
+
systemId?: string;
|
38
39
|
history?: ConversationItem[];
|
39
40
|
prompt: T;
|
40
41
|
}
|
@@ -78,6 +79,7 @@ export declare enum HTMLPageEncoding {
|
|
78
79
|
}
|
79
80
|
export interface ImplementAPIClients {
|
80
81
|
pages: HTMLPage[];
|
82
|
+
systemId: string;
|
81
83
|
}
|
82
84
|
export interface HTMLPage {
|
83
85
|
fileName: string;
|
@@ -7,13 +7,14 @@ export declare class StormService {
|
|
7
7
|
id: string;
|
8
8
|
description: string;
|
9
9
|
title: string;
|
10
|
+
url?: string | undefined;
|
10
11
|
}[]>;
|
11
12
|
getConversation(conversationId: string): Promise<string>;
|
12
13
|
saveConversation(conversationId: string, events: StormEvent[]): Promise<void>;
|
13
14
|
appendConversation(conversationId: string, events: StormEvent[]): Promise<void>;
|
14
15
|
deleteConversation(conversationId: string): Promise<void>;
|
15
|
-
uploadConversation(handle: string,
|
16
|
-
installProjectById(handle: string,
|
16
|
+
uploadConversation(handle: string, systemId: string): Promise<void>;
|
17
|
+
installProjectById(handle: string, systemId: string): Promise<void>;
|
17
18
|
}
|
18
19
|
declare const _default: StormService;
|
19
20
|
export default _default;
|
@@ -54,22 +54,43 @@ class StormService {
|
|
54
54
|
// Returns list of UUIDs - probably want to make it more useful than that
|
55
55
|
const conversations = [];
|
56
56
|
for (const file of eventFiles) {
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
57
|
+
try {
|
58
|
+
const nldContents = await promises_1.default.readFile(file, 'utf8');
|
59
|
+
const events = nldContents.split('\n').map((e) => JSON.parse(e));
|
60
|
+
// find the shell and get the title tag
|
61
|
+
const shellEvent = events.find((e) => e.type === 'AI' && e.event.type === 'UI_SHELL')?.event;
|
62
|
+
const html = shellEvent?.payload.content;
|
63
|
+
const title = html?.match(/<title>(.*?)<\/title>/)?.[1];
|
64
|
+
const id = events.find((e) => e.type === 'AI')?.systemId;
|
65
|
+
const initialPrompt = events.find((e) => e.type === 'AI' && e.event.type === 'PROMPT_IMPROVE')?.event?.payload?.prompt || events[0].text;
|
66
|
+
if (!id) {
|
67
|
+
continue;
|
68
|
+
}
|
69
|
+
let url = undefined;
|
70
|
+
// Find the last model response event that has a URL in the payload (in case it changed over time)
|
71
|
+
for (const evt of [...events].reverse()) {
|
72
|
+
const event = evt.event;
|
73
|
+
if (evt.type === 'AI' && event.type === 'MODEL_RESPONSE') {
|
74
|
+
// Look for a URL in the model response markdown
|
75
|
+
const regex = /\[(.*?)\]\((.*?)\)/g;
|
76
|
+
const match = regex.exec(event.payload.text);
|
77
|
+
const [, _linkText, linkUrl] = match || [];
|
78
|
+
if (linkUrl?.startsWith('http')) {
|
79
|
+
url = linkUrl;
|
80
|
+
break;
|
81
|
+
}
|
82
|
+
}
|
83
|
+
}
|
84
|
+
conversations.push({
|
85
|
+
id,
|
86
|
+
description: initialPrompt,
|
87
|
+
title: title || 'New system',
|
88
|
+
url,
|
89
|
+
});
|
90
|
+
}
|
91
|
+
catch (e) {
|
92
|
+
console.error('Failed to load conversation at %s', file, e);
|
67
93
|
}
|
68
|
-
conversations.push({
|
69
|
-
id,
|
70
|
-
description: initialPrompt,
|
71
|
-
title: title || 'New system',
|
72
|
-
});
|
73
94
|
}
|
74
95
|
return conversations;
|
75
96
|
}
|
@@ -98,8 +119,8 @@ class StormService {
|
|
98
119
|
await promises_1.default.rm(conversationDir, { recursive: true, force: true });
|
99
120
|
}
|
100
121
|
}
|
101
|
-
async uploadConversation(handle,
|
102
|
-
const tarballFile = this.getConversationTarball(
|
122
|
+
async uploadConversation(handle, systemId) {
|
123
|
+
const tarballFile = this.getConversationTarball(systemId);
|
103
124
|
const destDir = path_1.default.dirname(tarballFile);
|
104
125
|
const tarballName = path_1.default.basename(tarballFile);
|
105
126
|
await tar.create({
|
@@ -108,12 +129,14 @@ class StormService {
|
|
108
129
|
gzip: true,
|
109
130
|
filter: (entry) => !entry.includes(tarballName),
|
110
131
|
}, ['.']);
|
111
|
-
|
132
|
+
const stormClient = new stormClient_1.StormClient(systemId);
|
133
|
+
await stormClient.uploadSystem(handle, systemId, await promises_1.default.readFile(tarballFile));
|
112
134
|
}
|
113
|
-
async installProjectById(handle,
|
114
|
-
const tarballFile = this.getConversationTarball(
|
135
|
+
async installProjectById(handle, systemId) {
|
136
|
+
const tarballFile = this.getConversationTarball(systemId);
|
115
137
|
const destDir = path_1.default.dirname(tarballFile);
|
116
|
-
const
|
138
|
+
const stormClient = new stormClient_1.StormClient(systemId);
|
139
|
+
const buffer = await stormClient.downloadSystem(handle, systemId);
|
117
140
|
await promises_1.default.mkdir(destDir, { recursive: true });
|
118
141
|
await promises_1.default.writeFile(tarballFile, buffer);
|
119
142
|
await tar.extract({
|
package/package.json
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
*/
|
5
5
|
|
6
6
|
import uuid from 'node-uuid';
|
7
|
-
import {
|
7
|
+
import { StormClient, UIPagePrompt } from './stormClient';
|
8
8
|
import { ReferenceClassification, StormEvent, StormEventPage, StormImage, UIShell } from './events';
|
9
9
|
import { EventEmitter } from 'node:events';
|
10
10
|
import PQueue from 'p-queue';
|
@@ -265,8 +265,9 @@ export class PageQueue extends EventEmitter {
|
|
265
265
|
return;
|
266
266
|
}
|
267
267
|
|
268
|
+
const client = new StormClient(this.systemId);
|
268
269
|
this.images.set(prompt.url, prompt.description);
|
269
|
-
const result = await
|
270
|
+
const result = await client.createImage(
|
270
271
|
`Create an image for the url "${prompt.url}" with this description: ${prompt.description}`.trim()
|
271
272
|
);
|
272
273
|
|
@@ -287,7 +288,8 @@ export class PageQueue extends EventEmitter {
|
|
287
288
|
}
|
288
289
|
|
289
290
|
public async generate(prompt: UIPagePrompt, conversationId: string) {
|
290
|
-
const
|
291
|
+
const client = new StormClient(this.systemId);
|
292
|
+
const screenStream = await client.createUIPage(prompt, conversationId);
|
291
293
|
let pageEvent: StormEventPage | null = null;
|
292
294
|
screenStream.on('data', (event: StormEvent) => {
|
293
295
|
if (event.type === 'PAGE') {
|
@@ -306,7 +308,8 @@ export class PageQueue extends EventEmitter {
|
|
306
308
|
}
|
307
309
|
|
308
310
|
private async resolveReferences(content: string): Promise<ReferenceClassification[]> {
|
309
|
-
const
|
311
|
+
const client = new StormClient(this.systemId);
|
312
|
+
const referenceStream = await client.classifyUIReferences(content);
|
310
313
|
|
311
314
|
const references: ReferenceClassification[] = [];
|
312
315
|
|
package/src/storm/codegen.ts
CHANGED
@@ -17,7 +17,7 @@ import {
|
|
17
17
|
|
18
18
|
import { BlockDefinition } from '@kapeta/schemas';
|
19
19
|
import { codeGeneratorManager } from '../codeGeneratorManager';
|
20
|
-
import { STORM_ID,
|
20
|
+
import { STORM_ID, StormClient } from './stormClient';
|
21
21
|
import {
|
22
22
|
StormEvent,
|
23
23
|
StormEventBlockStatusType,
|
@@ -371,6 +371,7 @@ export class StormCodegen {
|
|
371
371
|
});
|
372
372
|
const uiEvents = [];
|
373
373
|
|
374
|
+
const stormClient = new StormClient(this.uiSystemId);
|
374
375
|
// generate screens
|
375
376
|
if (uiTemplates.length) {
|
376
377
|
const screenStream = await stormClient.listScreens({
|
@@ -663,6 +664,7 @@ export class StormCodegen {
|
|
663
664
|
}
|
664
665
|
|
665
666
|
private async classifyErrors(errors: string, basePath: string): Promise<Map<string, ErrorClassification[]>> {
|
667
|
+
const stormClient = new StormClient(this.uiSystemId);
|
666
668
|
const errorStream = await stormClient.createErrorClassification(errors, []);
|
667
669
|
const fixes = new Map<string, ErrorClassification[]>();
|
668
670
|
|
@@ -711,7 +713,7 @@ export class StormCodegen {
|
|
711
713
|
error: error,
|
712
714
|
projectFiles: allFiles.map((f) => f.filename),
|
713
715
|
};
|
714
|
-
|
716
|
+
const stormClient = new StormClient(this.uiSystemId);
|
715
717
|
const detailsStream = await stormClient.createErrorDetails(JSON.stringify(request), []);
|
716
718
|
detailsStream.on('data', (evt) => {
|
717
719
|
if (evt.type === 'ERROR_DETAILS') {
|
@@ -799,6 +801,7 @@ export class StormCodegen {
|
|
799
801
|
): Promise<StormEventErrorDetailsFile> {
|
800
802
|
return new Promise<StormEventErrorDetailsFile>(async (resolve, reject) => {
|
801
803
|
try {
|
804
|
+
const stormClient = new StormClient(this.uiSystemId);
|
802
805
|
const fixStream = await stormClient.createCodeFix(fix, history, this.conversationId);
|
803
806
|
let resolved = false;
|
804
807
|
fixStream.on('data', (evt) => {
|
package/src/storm/events.ts
CHANGED
@@ -480,7 +480,16 @@ export interface StormEventSystemReady {
|
|
480
480
|
created: number;
|
481
481
|
payload: {
|
482
482
|
systemUrl: string;
|
483
|
-
}
|
483
|
+
};
|
484
|
+
}
|
485
|
+
|
486
|
+
export interface StormEventModelResponse {
|
487
|
+
type: 'MODEL_RESPONSE';
|
488
|
+
reason: string;
|
489
|
+
created: number;
|
490
|
+
payload: {
|
491
|
+
text: string;
|
492
|
+
};
|
484
493
|
}
|
485
494
|
|
486
495
|
export type StormEvent =
|
@@ -518,4 +527,5 @@ export type StormEvent =
|
|
518
527
|
| StormEventApiBase
|
519
528
|
| StormEventUIStarted
|
520
529
|
| StormImage
|
521
|
-
| StormEventSystemReady
|
530
|
+
| StormEventSystemReady
|
531
|
+
| StormEventModelResponse;
|
package/src/storm/routes.ts
CHANGED
@@ -21,12 +21,12 @@ import {
|
|
21
21
|
|
22
22
|
import {
|
23
23
|
ConversationIdHeader,
|
24
|
-
stormClient,
|
25
24
|
UIPagePrompt,
|
26
25
|
UIPageEditRequest,
|
27
26
|
BasePromptRequest,
|
28
27
|
UIPageVoteRequest,
|
29
28
|
UIPageGetVoteRequest,
|
29
|
+
StormClient,
|
30
30
|
} from './stormClient';
|
31
31
|
import { StormEvent, StormEventPage, StormEventPhaseType, UserJourneyScreen } from './events';
|
32
32
|
|
@@ -162,9 +162,12 @@ router.post('/ui/create-system/:handle/:systemId', async (req: KapetaBodyRequest
|
|
162
162
|
sendEvent(res, createPhaseStartEvent(StormEventPhaseType.IMPLEMENT_APIS));
|
163
163
|
|
164
164
|
const pagesFromDisk = readFilesAndContent(srcDir);
|
165
|
-
const
|
165
|
+
const client = new StormClient(systemId)
|
166
|
+
const pagesWithImplementation = await client.replaceMockWithAPICall({
|
166
167
|
pages: pagesFromDisk,
|
168
|
+
systemId: systemId,
|
167
169
|
});
|
170
|
+
|
168
171
|
await copyDirectory(srcDir, destDir, (fileName, content) => {
|
169
172
|
// find the page from result1 and write the content to the file
|
170
173
|
const page = pagesWithImplementation.find((p) => p.fileName === fileName);
|
@@ -180,7 +183,7 @@ router.post('/ui/create-system/:handle/:systemId', async (req: KapetaBodyRequest
|
|
180
183
|
return page.content;
|
181
184
|
});
|
182
185
|
|
183
|
-
const prompt = await
|
186
|
+
const prompt = await client.generatePrompt(pageContents);
|
184
187
|
|
185
188
|
sendEvent(res, createPhaseEndEvent(StormEventPhaseType.COMPOSE_SYSTEM_PROMPT));
|
186
189
|
|
@@ -203,11 +206,12 @@ router.post('/ui/create-system-simple/:handle/:systemId', async (req: KapetaBody
|
|
203
206
|
//res.set(ConversationIdHeader, systemId);
|
204
207
|
|
205
208
|
//sendEvent(res, createPhaseStartEvent(StormEventPhaseType.IMPLEMENT_APIS));
|
206
|
-
|
209
|
+
const client = new StormClient(systemId);
|
207
210
|
try {
|
208
211
|
const pagesFromDisk = readFilesAndContent(srcDir);
|
209
|
-
const pagesWithImplementation = await
|
212
|
+
const pagesWithImplementation = await client.replaceMockWithAPICall({
|
210
213
|
pages: pagesFromDisk,
|
214
|
+
systemId: systemId,
|
211
215
|
});
|
212
216
|
|
213
217
|
//sendEvent(res, createPhaseEndEvent(StormEventPhaseType.IMPLEMENT_APIS));
|
@@ -226,7 +230,7 @@ router.post('/ui/create-system-simple/:handle/:systemId', async (req: KapetaBody
|
|
226
230
|
return page;
|
227
231
|
});
|
228
232
|
|
229
|
-
const systemUrl = await
|
233
|
+
const systemUrl = await client.createSimpleBackend(handle, systemId, { pages: allFiles });
|
230
234
|
//sendEvent(res, {type: 'SYSTEM_READY', created: Math.floor(Date.now() / 1000), reason: 'System Ready', payload: { systemUrl: systemUrl }});
|
231
235
|
|
232
236
|
//sendEvent(res, createPhaseEndEvent(StormEventPhaseType.COMPOSE_SYSTEM));
|
@@ -327,8 +331,8 @@ router.post('/:handle/ui/iterative', async (req: KapetaBodyRequest, res: Respons
|
|
327
331
|
const conversationId = req.headers[ConversationIdHeader.toLowerCase()] as string | undefined;
|
328
332
|
|
329
333
|
const aiRequest: BasePromptRequest = JSON.parse(req.stringBody ?? '{}');
|
330
|
-
|
331
|
-
const landingPagesStream = await
|
334
|
+
const client = new StormClient(conversationId); //todo is this correct we are using the landing page getConversationId down below as well
|
335
|
+
const landingPagesStream = await client.createUILandingPages(aiRequest, conversationId);
|
332
336
|
|
333
337
|
onRequestAborted(req, res, () => {
|
334
338
|
landingPagesStream.abort();
|
@@ -436,7 +440,7 @@ router.post('/:handle/ui', async (req: KapetaBodyRequest, res: Response) => {
|
|
436
440
|
(req.headers[ConversationIdHeader.toLowerCase()] as string | undefined) || randomUUID();
|
437
441
|
|
438
442
|
const aiRequest: BasePromptRequest = JSON.parse(req.stringBody ?? '{}');
|
439
|
-
|
443
|
+
const stormClient = new StormClient(outerConversationId);
|
440
444
|
// Get user journeys
|
441
445
|
const userJourneysStream = await stormClient.createUIUserJourneys(aiRequest, outerConversationId);
|
442
446
|
|
@@ -718,6 +722,7 @@ router.post('/ui/vote', async (req: KapetaBodyRequest, res: Response) => {
|
|
718
722
|
const aiRequest: UIPageVoteRequest = JSON.parse(req.stringBody ?? '{}');
|
719
723
|
const { topic, vote, mainConversationId } = aiRequest;
|
720
724
|
try {
|
725
|
+
const stormClient = new StormClient(mainConversationId);
|
721
726
|
await stormClient.voteUIPage(topic, conversationId, vote, mainConversationId);
|
722
727
|
} catch (e: any) {
|
723
728
|
res.status(500).send({ error: e.message });
|
@@ -729,6 +734,7 @@ router.post('/ui/get-vote', async (req: KapetaBodyRequest, res: Response) => {
|
|
729
734
|
const aiRequest: UIPageGetVoteRequest = JSON.parse(req.stringBody ?? '{}');
|
730
735
|
const { topic, mainConversationId } = aiRequest;
|
731
736
|
try {
|
737
|
+
const stormClient = new StormClient(mainConversationId);
|
732
738
|
const vote = await stormClient.getVoteUIPage(topic, conversationId, mainConversationId);
|
733
739
|
res.send({ vote });
|
734
740
|
} catch (e: any) {
|
@@ -760,6 +766,7 @@ async function handleAll(req: KapetaBodyRequest, res: Response) {
|
|
760
766
|
const conversationId = req.headers[ConversationIdHeader.toLowerCase()] as string | undefined;
|
761
767
|
|
762
768
|
const aiRequest: BasePromptRequest = JSON.parse(req.stringBody ?? '{}');
|
769
|
+
const stormClient = new StormClient(systemId);
|
763
770
|
const metaStream = await stormClient.createMetadata(aiRequest, conversationId);
|
764
771
|
|
765
772
|
onRequestAborted(req, res, () => {
|
package/src/storm/stormClient.ts
CHANGED
@@ -24,6 +24,7 @@ const fetchWithRetries = createFetch(global.fetch, { retries: 5, retryDelay: 10
|
|
24
24
|
export const STORM_ID = 'storm';
|
25
25
|
|
26
26
|
export const ConversationIdHeader = 'Conversation-Id';
|
27
|
+
export const SystemIdHeader = 'System-Id';
|
27
28
|
|
28
29
|
export interface UIShellsPrompt {
|
29
30
|
theme?: string;
|
@@ -85,11 +86,12 @@ export interface BasePromptRequest {
|
|
85
86
|
skipImprovement?: boolean;
|
86
87
|
}
|
87
88
|
|
88
|
-
class StormClient {
|
89
|
+
export class StormClient {
|
89
90
|
private readonly _baseUrl: string;
|
90
|
-
|
91
|
-
constructor() {
|
91
|
+
private readonly _systemId: string;
|
92
|
+
constructor(systemId?: string) {
|
92
93
|
this._baseUrl = getRemoteUrl('ai-service', 'https://ai.kapeta.com');
|
94
|
+
this._systemId = systemId || "";
|
93
95
|
}
|
94
96
|
|
95
97
|
private async createOptions(
|
@@ -110,7 +112,9 @@ class StormClient {
|
|
110
112
|
if (body.conversationId) {
|
111
113
|
headers[ConversationIdHeader] = body.conversationId;
|
112
114
|
}
|
113
|
-
|
115
|
+
if (this._systemId) {
|
116
|
+
headers[SystemIdHeader] = this._systemId
|
117
|
+
}
|
114
118
|
return {
|
115
119
|
url,
|
116
120
|
method: method,
|
@@ -130,7 +134,6 @@ class StormClient {
|
|
130
134
|
prompt: stringPrompt,
|
131
135
|
conversationId: body.conversationId,
|
132
136
|
});
|
133
|
-
|
134
137
|
const abort = new AbortController();
|
135
138
|
options.signal = abort.signal;
|
136
139
|
|
@@ -202,6 +205,7 @@ class StormClient {
|
|
202
205
|
public createUIShells(prompt: UIShellsPrompt, conversationId?: string) {
|
203
206
|
return this.send('/v2/ui/shells', {
|
204
207
|
prompt: JSON.stringify(prompt),
|
208
|
+
conversationId: conversationId,
|
205
209
|
});
|
206
210
|
}
|
207
211
|
|
@@ -245,6 +249,9 @@ class StormClient {
|
|
245
249
|
const response = await fetch(u, {
|
246
250
|
method: 'POST',
|
247
251
|
body: JSON.stringify(prompt.pages),
|
252
|
+
headers: {
|
253
|
+
'systemId': prompt.systemId,
|
254
|
+
},
|
248
255
|
});
|
249
256
|
return (await response.json()) as HTMLPage[];
|
250
257
|
}
|
@@ -377,5 +384,3 @@ class StormClient {
|
|
377
384
|
return response;
|
378
385
|
}
|
379
386
|
}
|
380
|
-
|
381
|
-
export const stormClient = new StormClient();
|
package/src/storm/stream.ts
CHANGED
@@ -99,6 +99,7 @@ export interface ConversationItem {
|
|
99
99
|
|
100
100
|
export interface StormContextRequest<T = string> {
|
101
101
|
conversationId?: string;
|
102
|
+
systemId?: string;
|
102
103
|
history?: ConversationItem[];
|
103
104
|
prompt: T;
|
104
105
|
}
|
@@ -150,6 +151,7 @@ export enum HTMLPageEncoding {
|
|
150
151
|
|
151
152
|
export interface ImplementAPIClients {
|
152
153
|
pages: HTMLPage[];
|
154
|
+
systemId: string;
|
153
155
|
}
|
154
156
|
|
155
157
|
export interface HTMLPage {
|