@kapeta/local-cluster-service 0.66.0 → 0.67.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.d.ts +14 -1
- package/dist/cjs/src/storm/PageGenerator.js +30 -7
- package/dist/cjs/src/storm/PromiseQueue.d.ts +7 -0
- package/dist/cjs/src/storm/PromiseQueue.js +27 -1
- package/dist/cjs/src/storm/events.d.ts +9 -1
- package/dist/cjs/src/storm/page-utils.d.ts +5 -1
- package/dist/cjs/src/storm/page-utils.js +30 -3
- package/dist/cjs/src/storm/routes.js +76 -47
- package/dist/cjs/src/storm/stormClient.d.ts +2 -1
- package/dist/cjs/src/storm/stormClient.js +6 -0
- package/dist/esm/src/storm/PageGenerator.d.ts +14 -1
- package/dist/esm/src/storm/PageGenerator.js +30 -7
- package/dist/esm/src/storm/PromiseQueue.d.ts +7 -0
- package/dist/esm/src/storm/PromiseQueue.js +27 -1
- package/dist/esm/src/storm/events.d.ts +9 -1
- package/dist/esm/src/storm/page-utils.d.ts +5 -1
- package/dist/esm/src/storm/page-utils.js +30 -3
- package/dist/esm/src/storm/routes.js +76 -47
- package/dist/esm/src/storm/stormClient.d.ts +2 -1
- package/dist/esm/src/storm/stormClient.js +6 -0
- package/package.json +1 -1
- package/src/storm/PageGenerator.ts +51 -15
- package/src/storm/PromiseQueue.ts +34 -0
- package/src/storm/events.ts +11 -1
- package/src/storm/page-utils.ts +38 -4
- package/src/storm/routes.ts +88 -54
- package/src/storm/stormClient.ts +8 -1
package/src/storm/routes.ts
CHANGED
@@ -23,7 +23,7 @@ import {
|
|
23
23
|
UIPageVoteRequest,
|
24
24
|
UIPageGetVoteRequest,
|
25
25
|
} from './stormClient';
|
26
|
-
import { Page, StormEvent, StormEventPage, StormEventPhaseType, UserJourneyScreen } from './events';
|
26
|
+
import { Page, StormEvent, StormEventPage, StormEventPhaseType, StormImage, UserJourneyScreen } from './events';
|
27
27
|
|
28
28
|
import {
|
29
29
|
createPhaseEndEvent,
|
@@ -40,11 +40,12 @@ import {
|
|
40
40
|
readPageFromDiskAsString,
|
41
41
|
SystemIdHeader,
|
42
42
|
writeAssetToDisk,
|
43
|
+
writeImageToDisk,
|
43
44
|
writePageToDisk,
|
44
45
|
} from './page-utils';
|
45
46
|
import { UIServer } from './UIServer';
|
46
|
-
import { PageQueue } from './PageGenerator';
|
47
47
|
import { randomUUID } from 'crypto';
|
48
|
+
import { ImagePrompt, PageQueue } from './PageGenerator';
|
48
49
|
|
49
50
|
const UI_SERVERS: { [key: string]: UIServer } = {};
|
50
51
|
const router = Router();
|
@@ -114,6 +115,21 @@ router.post('/ui/screen', async (req: KapetaBodyRequest, res: Response) => {
|
|
114
115
|
}
|
115
116
|
});
|
116
117
|
|
118
|
+
queue.on('image', async (screenData, prompt, future) => {
|
119
|
+
if (!systemId) {
|
120
|
+
return;
|
121
|
+
}
|
122
|
+
try {
|
123
|
+
const promise = handleImageEvent(systemId, screenData, prompt);
|
124
|
+
promises.push(promise);
|
125
|
+
await promise;
|
126
|
+
future.resolve();
|
127
|
+
} catch (e) {
|
128
|
+
console.error('Failed to handle image event', e);
|
129
|
+
future.reject(e);
|
130
|
+
}
|
131
|
+
});
|
132
|
+
|
117
133
|
await queue.addPrompt(aiRequest, conversationId, true);
|
118
134
|
|
119
135
|
await queue.wait();
|
@@ -211,6 +227,18 @@ router.post('/:handle/ui/iterative', async (req: KapetaBodyRequest, res: Respons
|
|
211
227
|
pageEventPromises.push(sendPageEvent(landingPagesStream.getConversationId(), screenData, res));
|
212
228
|
});
|
213
229
|
|
230
|
+
pageQueue.on('image', async (screenData, prompt, future) => {
|
231
|
+
try {
|
232
|
+
const promise = handleImageEvent(landingPagesStream.getConversationId(), screenData, prompt);
|
233
|
+
pageEventPromises.push(promise);
|
234
|
+
await promise;
|
235
|
+
future.resolve();
|
236
|
+
} catch (e) {
|
237
|
+
console.error('Failed to handle image event', e);
|
238
|
+
future.reject(e);
|
239
|
+
}
|
240
|
+
});
|
241
|
+
|
214
242
|
pageQueue.on('event', (screenData: StormEvent) => {
|
215
243
|
sendEvent(res, screenData);
|
216
244
|
});
|
@@ -347,7 +375,7 @@ router.post('/:handle/ui', async (req: KapetaBodyRequest, res: Response) => {
|
|
347
375
|
queue.setUiTheme(theme);
|
348
376
|
|
349
377
|
shellsStream.on('data', (data: StormEvent) => {
|
350
|
-
console.log('Processing shell event', data);
|
378
|
+
//console.log('Processing shell event', data);
|
351
379
|
sendEvent(res, data);
|
352
380
|
|
353
381
|
if (data.type !== 'UI_SHELL') {
|
@@ -394,6 +422,18 @@ router.post('/:handle/ui', async (req: KapetaBodyRequest, res: Response) => {
|
|
394
422
|
pageEventPromises.push(sendPageEvent(outerConversationId, screenData, res));
|
395
423
|
});
|
396
424
|
|
425
|
+
queue.on('image', async (screenData, prompt, future) => {
|
426
|
+
try {
|
427
|
+
const promise = handleImageEvent(outerConversationId, screenData, prompt);
|
428
|
+
pageEventPromises.push(promise);
|
429
|
+
await promise;
|
430
|
+
future.resolve();
|
431
|
+
} catch (e) {
|
432
|
+
console.error('Failed to handle image event', e);
|
433
|
+
future.reject(e);
|
434
|
+
}
|
435
|
+
});
|
436
|
+
|
397
437
|
queue.on('event', (screenData: StormEvent) => {
|
398
438
|
sendEvent(res, screenData);
|
399
439
|
});
|
@@ -433,67 +473,53 @@ router.post('/:handle/ui', async (req: KapetaBodyRequest, res: Response) => {
|
|
433
473
|
|
434
474
|
router.post('/ui/edit', async (req: KapetaBodyRequest, res: Response) => {
|
435
475
|
try {
|
436
|
-
const
|
476
|
+
const systemId = (req.headers[SystemIdHeader.toLowerCase()] ||
|
477
|
+
req.headers[ConversationIdHeader.toLowerCase()]) as string | undefined;
|
437
478
|
|
438
479
|
const aiRequest: StormContextRequest<UIPageEditRequest> = JSON.parse(req.stringBody ?? '{}');
|
439
|
-
|
440
|
-
const
|
441
|
-
.map((page) => {
|
442
|
-
const content = readPageFromDiskAsString(conversationId!, page.path, page.method);
|
443
|
-
if (!content) {
|
444
|
-
console.warn('Page not found', page);
|
445
|
-
return undefined;
|
446
|
-
}
|
447
|
-
|
448
|
-
return {
|
449
|
-
filename: page.filename,
|
450
|
-
path: page.path,
|
451
|
-
method: page.method,
|
452
|
-
title: page.title,
|
453
|
-
conversationId: page.conversationId,
|
454
|
-
prompt: page.prompt,
|
455
|
-
name: page.name,
|
456
|
-
description: page.description,
|
457
|
-
content,
|
458
|
-
} satisfies Page;
|
459
|
-
})
|
460
|
-
.filter((page: Page | undefined) => !!page) as UIPageEditPrompt['pages'];
|
461
|
-
|
462
|
-
const editStream = await stormClient.editPages(
|
463
|
-
{
|
464
|
-
prompt: aiRequest.prompt.prompt.prompt,
|
465
|
-
blockDescription: aiRequest.prompt.blockDescription,
|
466
|
-
planDescription: aiRequest.prompt.planDescription,
|
467
|
-
pages,
|
468
|
-
},
|
469
|
-
conversationId
|
470
|
-
);
|
480
|
+
const storagePrefix = systemId ? systemId + '_' : 'mock_';
|
481
|
+
const queue = new PageQueue(storagePrefix, 5);
|
471
482
|
|
472
483
|
onRequestAborted(req, res, () => {
|
473
|
-
|
484
|
+
queue.cancel();
|
474
485
|
});
|
475
486
|
|
476
|
-
res.set('Content-Type', 'application/x-ndjson');
|
477
|
-
res.set('Access-Control-Expose-Headers', ConversationIdHeader);
|
478
|
-
res.set(ConversationIdHeader, editStream.getConversationId());
|
479
|
-
|
480
487
|
const promises: Promise<void>[] = [];
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
} else {
|
486
|
-
sendEvent(res, data);
|
487
|
-
}
|
488
|
-
} catch (e) {
|
489
|
-
console.error('Failed to process event', e);
|
488
|
+
|
489
|
+
queue.on('page', (data) => {
|
490
|
+
if (systemId) {
|
491
|
+
promises.push(sendPageEvent(systemId, data, res));
|
490
492
|
}
|
491
493
|
});
|
492
494
|
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
495
|
+
queue.on('event', (data) => {
|
496
|
+
if (data.type === 'FILE_START' || data.type === 'FILE_DONE' || data.type === 'FILE_STATE') {
|
497
|
+
sendEvent(res, data);
|
498
|
+
}
|
499
|
+
});
|
500
|
+
|
501
|
+
await Promise.allSettled(
|
502
|
+
aiRequest.prompt.pages.map((page) => {
|
503
|
+
if (page.conversationId) {
|
504
|
+
return queue.addPrompt(
|
505
|
+
{
|
506
|
+
title: page.title,
|
507
|
+
name: page.name,
|
508
|
+
method: page.method,
|
509
|
+
path: page.path,
|
510
|
+
description: page.description ?? '',
|
511
|
+
filename: page.filename,
|
512
|
+
prompt: aiRequest.prompt.prompt.prompt,
|
513
|
+
storage_prefix: storagePrefix,
|
514
|
+
},
|
515
|
+
page.conversationId,
|
516
|
+
true
|
517
|
+
);
|
518
|
+
}
|
519
|
+
})
|
520
|
+
);
|
521
|
+
|
522
|
+
await queue.wait();
|
497
523
|
await Promise.all(promises);
|
498
524
|
|
499
525
|
sendDone(res);
|
@@ -766,4 +792,12 @@ async function sendPageEvent(mainConversationId: string, data: StormEventPage, r
|
|
766
792
|
sendEvent(res, convertPageEvent(data, data.payload.conversationId, mainConversationId));
|
767
793
|
}
|
768
794
|
|
795
|
+
async function handleImageEvent(mainConversationId: string, data: StormImage, prompt: ImagePrompt) {
|
796
|
+
try {
|
797
|
+
await writeImageToDisk(mainConversationId, data, prompt);
|
798
|
+
} catch (err) {
|
799
|
+
console.error('Failed to write image to disk', err);
|
800
|
+
}
|
801
|
+
}
|
802
|
+
|
769
803
|
export default router;
|
package/src/storm/stormClient.ts
CHANGED
@@ -44,7 +44,7 @@ export interface UIPagePrompt {
|
|
44
44
|
storage_prefix: string;
|
45
45
|
shell_page?: string;
|
46
46
|
// contents of theme.css
|
47
|
-
theme
|
47
|
+
theme?: string;
|
48
48
|
}
|
49
49
|
|
50
50
|
export interface UIPageSamplePrompt extends UIPagePrompt {
|
@@ -263,6 +263,13 @@ class StormClient {
|
|
263
263
|
});
|
264
264
|
}
|
265
265
|
|
266
|
+
public createImage(prompt: string, conversationId?: string) {
|
267
|
+
return this.send('/v2/ui/image', {
|
268
|
+
prompt,
|
269
|
+
conversationId,
|
270
|
+
});
|
271
|
+
}
|
272
|
+
|
266
273
|
public createUIImplementation(prompt: StormUIImplementationPrompt, conversationId?: string) {
|
267
274
|
return this.send('/v2/ui/merge', {
|
268
275
|
prompt,
|