@kapeta/local-cluster-service 0.65.0 → 0.67.0

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.
@@ -18,6 +18,7 @@ class PageQueue extends node_events_1.EventEmitter {
18
18
  systemId;
19
19
  references = new Map();
20
20
  uiShells = [];
21
+ theme = '';
21
22
  constructor(systemId, concurrency = 5) {
22
23
  super();
23
24
  this.systemId = systemId;
@@ -32,18 +33,22 @@ class PageQueue extends node_events_1.EventEmitter {
32
33
  addUiShell(uiShell) {
33
34
  this.uiShells.push(uiShell);
34
35
  }
36
+ setUiTheme(theme) {
37
+ this.theme = theme;
38
+ }
35
39
  addPrompt(initialPrompt, conversationId = node_uuid_1.default.v4(), overwrite = false) {
36
40
  if (!overwrite && this.references.has(initialPrompt.path)) {
37
- console.log('Ignoring duplicate prompt', initialPrompt.path);
41
+ //console.log('Ignoring duplicate prompt', initialPrompt.path);
38
42
  return Promise.resolve();
39
43
  }
40
44
  if (!overwrite && (0, page_utils_1.hasPageOnDisk)(this.systemId, initialPrompt.method, initialPrompt.path)) {
41
- console.log('Ignoring prompt with existing page', initialPrompt.path);
45
+ //console.log('Ignoring prompt with existing page', initialPrompt.path);
42
46
  return Promise.resolve();
43
47
  }
44
48
  const prompt = {
45
49
  ...initialPrompt,
46
50
  shell_page: this.uiShells.find((shell) => shell.screens.includes(initialPrompt.name))?.content,
51
+ theme: this.theme,
47
52
  };
48
53
  const generator = new PageGenerator(prompt, conversationId);
49
54
  this.references.set(prompt.path, generator);
@@ -51,9 +56,8 @@ class PageQueue extends node_events_1.EventEmitter {
51
56
  }
52
57
  async addPageGenerator(generator) {
53
58
  generator.on('event', (event) => this.emit('event', event));
54
- generator.on('page_refs', ({ event, references }) => {
55
- this.emit('page', event);
56
- references.forEach((reference) => {
59
+ generator.on('page_refs', async ({ event, references }) => {
60
+ const promises = references.map(async (reference) => {
57
61
  if (reference.url.startsWith('#') ||
58
62
  reference.url.startsWith('javascript:') ||
59
63
  reference.url.startsWith('http://') ||
@@ -62,14 +66,17 @@ class PageQueue extends node_events_1.EventEmitter {
62
66
  }
63
67
  switch (reference.type) {
64
68
  case 'image':
65
- console.log('Ignoring image reference', reference);
69
+ await this.addImagePrompt({
70
+ ...reference,
71
+ content: event.payload.content,
72
+ });
66
73
  break;
67
74
  case 'css':
68
75
  case 'javascript':
69
76
  //console.log('Ignoring reference', reference);
70
77
  break;
71
78
  case 'html':
72
- console.log('Adding page generator for', reference);
79
+ //console.log('Adding page generator for', reference);
73
80
  const paths = Array.from(this.references.keys());
74
81
  this.addPrompt({
75
82
  name: reference.name,
@@ -84,10 +91,13 @@ class PageQueue extends node_events_1.EventEmitter {
84
91
  : ''),
85
92
  description: reference.description,
86
93
  filename: '',
94
+ theme: this.theme,
87
95
  });
88
96
  break;
89
97
  }
90
98
  });
99
+ await Promise.allSettled(promises);
100
+ this.emit('page', event);
91
101
  });
92
102
  return this.queue.add(() => generator.generate());
93
103
  }
@@ -97,6 +107,25 @@ class PageQueue extends node_events_1.EventEmitter {
97
107
  wait() {
98
108
  return this.queue.wait();
99
109
  }
110
+ async addImagePrompt(prompt) {
111
+ const result = await stormClient_1.stormClient.createImage(`Create an image for the url "${prompt.url}" with this description: ${prompt.description}`.trim());
112
+ const futures = [];
113
+ result.on('data', async (event) => {
114
+ if (event.type === 'IMAGE') {
115
+ const future = (0, PromiseQueue_1.createFuture)();
116
+ futures.push(future);
117
+ this.emit('image', event, prompt, future);
118
+ setTimeout(() => {
119
+ if (!future.isResolved()) {
120
+ console.log('Image prompt timed out', prompt);
121
+ future.reject(new Error('Image prompt timed out'));
122
+ }
123
+ }, 30000);
124
+ }
125
+ });
126
+ await result.waitForDone();
127
+ await Promise.allSettled(futures.map((f) => f.promise));
128
+ }
100
129
  }
101
130
  exports.PageQueue = PageQueue;
102
131
  class PageGenerator extends node_events_1.EventEmitter {
@@ -3,6 +3,13 @@
3
3
  * SPDX-License-Identifier: BUSL-1.1
4
4
  */
5
5
  export type Future<T> = () => Promise<T>;
6
+ export type FuturePromise<T> = {
7
+ promise: Promise<T>;
8
+ resolve: (value: T) => void;
9
+ reject: (reason: any) => void;
10
+ isResolved: () => boolean;
11
+ };
12
+ export declare function createFuture<T = void>(): FuturePromise<T>;
6
13
  export declare class PromiseQueue {
7
14
  private readonly queue;
8
15
  private readonly active;
@@ -1,6 +1,32 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.PromiseQueue = void 0;
3
+ exports.PromiseQueue = exports.createFuture = void 0;
4
+ function createFuture() {
5
+ let resolved = false;
6
+ let resolve = () => {
7
+ resolved = true;
8
+ };
9
+ let reject = () => {
10
+ resolved = true;
11
+ };
12
+ const promise = new Promise((res, rej) => {
13
+ resolve = (value) => {
14
+ resolved = true;
15
+ res(value);
16
+ };
17
+ reject = (reason) => {
18
+ resolved = true;
19
+ rej(reason);
20
+ };
21
+ });
22
+ return {
23
+ promise,
24
+ resolve,
25
+ reject,
26
+ isResolved: () => resolved,
27
+ };
28
+ }
29
+ exports.createFuture = createFuture;
4
30
  class PromiseQueue {
5
31
  queue = [];
6
32
  active = [];
@@ -12,6 +12,7 @@ const express_1 = __importDefault(require("express"));
12
12
  const page_utils_1 = require("./page-utils");
13
13
  const clusterService_1 = require("../clusterService");
14
14
  const http_1 = require("http");
15
+ const path_1 = require("path");
15
16
  class UIServer {
16
17
  systemId;
17
18
  port = 50000;
@@ -28,6 +29,8 @@ class UIServer {
28
29
  window.sessionStorage.clear();
29
30
  </script>`);
30
31
  });
32
+ // Make it possible to serve static assets
33
+ app.use(express_1.default.static((0, path_1.join)((0, page_utils_1.getSystemBaseDir)(this.systemId), 'public'), { fallthrough: true }));
31
34
  app.all('/*', (req, res) => {
32
35
  (0, page_utils_1.readPageFromDisk)(this.systemId, req.params[0], req.method, res);
33
36
  });
@@ -255,6 +255,14 @@ export interface StormEventDone {
255
255
  type: 'DONE';
256
256
  created: number;
257
257
  }
258
+ export interface StormImage {
259
+ type: 'IMAGE';
260
+ reason: string;
261
+ created: number;
262
+ payload: {
263
+ href: string;
264
+ };
265
+ }
258
266
  export interface StormEventDefinitionChange {
259
267
  type: 'DEFINITION_CHANGE';
260
268
  reason: string;
@@ -384,5 +392,5 @@ export interface StormEventUIStarted {
384
392
  resetUrl: string;
385
393
  };
386
394
  }
387
- export type StormEvent = StormEventCreateBlock | StormEventCreateConnection | StormEventCreatePlanProperties | StormEventInvalidResponse | StormEventPlanRetry | StormEventCreateDSL | StormEventCreateDSLResource | StormEventError | StormEventScreen | StormEventScreenCandidate | StormEventFileLogical | StormEventFileState | StormEventFileDone | StormEventFileFailed | StormEventFileChunk | StormEventDone | StormEventDefinitionChange | StormEventErrorClassifier | StormEventCodeFix | StormEventErrorDetails | StormEventBlockReady | StormEventPhases | StormEventBlockStatus | StormEventCreateDSLRetry | StormEventUserJourney | StormEventUIShell | StormEventPage | StormEventPageUrl | StormEventPromptImprove | StormEventLandingPage | StormEventReferenceClassification | StormEventApiBase | StormEventUIStarted;
395
+ export type StormEvent = StormEventCreateBlock | StormEventCreateConnection | StormEventCreatePlanProperties | StormEventInvalidResponse | StormEventPlanRetry | StormEventCreateDSL | StormEventCreateDSLResource | StormEventError | StormEventScreen | StormEventScreenCandidate | StormEventFileLogical | StormEventFileState | StormEventFileDone | StormEventFileFailed | StormEventFileChunk | StormEventDone | StormEventDefinitionChange | StormEventErrorClassifier | StormEventCodeFix | StormEventErrorDetails | StormEventBlockReady | StormEventPhases | StormEventBlockStatus | StormEventCreateDSLRetry | StormEventUserJourney | StormEventUIShell | StormEventPage | StormEventPageUrl | StormEventPromptImprove | StormEventLandingPage | StormEventReferenceClassification | StormEventApiBase | StormEventUIStarted | StormImage;
388
396
  export {};
@@ -2,14 +2,22 @@
2
2
  * Copyright 2023 Kapeta Inc.
3
3
  * SPDX-License-Identifier: BUSL-1.1
4
4
  */
5
- import { StormEventPage } from './events';
5
+ import { StormEventFileDone, StormEventPage, StormImage } from './events';
6
6
  import { Response } from 'express';
7
7
  import { ConversationItem } from './stream';
8
+ import { ImagePrompt } from './PageGenerator';
8
9
  export declare const SystemIdHeader = "System-Id";
9
10
  export declare function writePageToDisk(systemId: string, event: StormEventPage): Promise<{
10
11
  path: string;
11
12
  }>;
13
+ export declare function writeAssetToDisk(systemId: string, event: StormEventFileDone): Promise<{
14
+ path: string;
15
+ }>;
16
+ export declare function writeImageToDisk(systemId: string, event: StormImage, prompt: ImagePrompt): Promise<{
17
+ path: string;
18
+ }>;
12
19
  export declare function hasPageOnDisk(systemId: string, method: string, path: string): boolean;
20
+ export declare function getSystemBaseDir(systemId: string): string;
13
21
  export declare function resolveReadPath(systemId: string, path: string, method: string): string | null;
14
22
  export declare function readPageFromDiskAsString(systemId: string, path: string, method: string): string | null;
15
23
  export declare function readPageFromDisk(systemId: string, path: string, method: string, res: Response): 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.writeConversationToFile = exports.readConversationFromFile = exports.readPageFromDisk = exports.readPageFromDiskAsString = exports.resolveReadPath = exports.hasPageOnDisk = exports.writePageToDisk = exports.SystemIdHeader = void 0;
6
+ exports.writeConversationToFile = exports.readConversationFromFile = exports.readPageFromDisk = exports.readPageFromDiskAsString = exports.resolveReadPath = exports.getSystemBaseDir = exports.hasPageOnDisk = exports.writeImageToDisk = exports.writeAssetToDisk = exports.writePageToDisk = exports.SystemIdHeader = void 0;
7
7
  const node_os_1 = __importDefault(require("node:os"));
8
8
  const path_1 = __importDefault(require("path"));
9
9
  const fs_extra_1 = __importDefault(require("fs-extra"));
@@ -15,7 +15,7 @@ function normalizePath(path) {
15
15
  .replace(/\{[a-z]+}/gi, '*');
16
16
  }
17
17
  async function writePageToDisk(systemId, event) {
18
- const baseDir = getBaseDir(systemId);
18
+ const baseDir = getSystemBaseDir(systemId);
19
19
  const filePath = getFilePath(event.payload.method);
20
20
  const path = path_1.default.join(baseDir, normalizePath(event.payload.path), filePath);
21
21
  await fs_extra_1.default.ensureDir(path_1.default.dirname(path));
@@ -26,24 +26,62 @@ async function writePageToDisk(systemId, event) {
26
26
  };
27
27
  }
28
28
  exports.writePageToDisk = writePageToDisk;
29
+ async function writeAssetToDisk(systemId, event) {
30
+ const baseDir = getSystemBaseDir(systemId);
31
+ const path = path_1.default.join(baseDir, 'public', event.payload.filename);
32
+ await fs_extra_1.default.ensureDir(path_1.default.dirname(path));
33
+ await fs_extra_1.default.writeFile(path, event.payload.content);
34
+ return {
35
+ path,
36
+ };
37
+ }
38
+ exports.writeAssetToDisk = writeAssetToDisk;
39
+ async function writeImageToDisk(systemId, event, prompt) {
40
+ const baseDir = getSystemBaseDir(systemId);
41
+ const path = path_1.default.join(baseDir, normalizePath(prompt.url));
42
+ const response = await fetch(event.payload.href);
43
+ if (!response.ok || !response.body) {
44
+ throw new Error(`Failed to fetch image: ${event.payload.href}`);
45
+ }
46
+ await fs_extra_1.default.ensureDir(path_1.default.dirname(path));
47
+ const buffer = await response.arrayBuffer();
48
+ await fs_extra_1.default.writeFile(path, Buffer.from(buffer));
49
+ console.log(`Image written to disk: ${event.payload.href} > ${path}`);
50
+ return {
51
+ path,
52
+ };
53
+ }
54
+ exports.writeImageToDisk = writeImageToDisk;
29
55
  function hasPageOnDisk(systemId, method, path) {
30
- const baseDir = getBaseDir(systemId);
56
+ const baseDir = getSystemBaseDir(systemId);
31
57
  const filePath = getFilePath(method);
32
58
  const fullPath = path_1.default.join(baseDir, normalizePath(path), filePath);
33
59
  return fs_extra_1.default.existsSync(fullPath);
34
60
  }
35
61
  exports.hasPageOnDisk = hasPageOnDisk;
36
- function getBaseDir(systemId) {
62
+ function getSystemBaseDir(systemId) {
37
63
  return path_1.default.join(node_os_1.default.tmpdir(), 'ai-systems', systemId);
38
64
  }
65
+ exports.getSystemBaseDir = getSystemBaseDir;
39
66
  function getFilePath(method) {
40
67
  return path_1.default.join(method.toLowerCase(), 'index.html');
41
68
  }
42
69
  function resolveReadPath(systemId, path, method) {
43
- const baseDir = getBaseDir(systemId);
70
+ const baseDir = getSystemBaseDir(systemId);
44
71
  path = normalizePath(path);
72
+ let fullPath = path_1.default.join(baseDir, path);
73
+ //First check if there is a file at the exact path
74
+ try {
75
+ const stat = fs_extra_1.default.statSync(fullPath);
76
+ if (stat && stat.isFile()) {
77
+ return fullPath;
78
+ }
79
+ }
80
+ catch (e) {
81
+ // Ignore
82
+ }
45
83
  const filePath = getFilePath(method);
46
- const fullPath = path_1.default.join(baseDir, path, filePath);
84
+ fullPath = path_1.default.join(baseDir, path, filePath);
47
85
  if (fs_extra_1.default.existsSync(fullPath)) {
48
86
  return fullPath;
49
87
  }
@@ -84,7 +122,7 @@ function readPageFromDisk(systemId, path, method, res) {
84
122
  return;
85
123
  }
86
124
  res.type(filePath.split('.').pop());
87
- const content = fs_extra_1.default.readFileSync(filePath, 'utf8');
125
+ const content = fs_extra_1.default.readFileSync(filePath);
88
126
  res.write(content);
89
127
  res.end();
90
128
  }
@@ -21,6 +21,7 @@ const assetManager_1 = require("../assetManager");
21
21
  const node_uuid_1 = __importDefault(require("node-uuid"));
22
22
  const page_utils_1 = require("./page-utils");
23
23
  const UIServer_1 = require("./UIServer");
24
+ const crypto_1 = require("crypto");
24
25
  const PageGenerator_1 = require("./PageGenerator");
25
26
  const UI_SERVERS = {};
26
27
  const router = (0, express_promise_router_1.default)();
@@ -77,6 +78,21 @@ router.post('/ui/screen', async (req, res) => {
77
78
  promises.push(sendPageEvent(systemId, data, res));
78
79
  }
79
80
  });
81
+ queue.on('image', async (screenData, prompt, future) => {
82
+ if (!systemId) {
83
+ return;
84
+ }
85
+ try {
86
+ const promise = handleImageEvent(systemId, screenData, prompt);
87
+ promises.push(promise);
88
+ await promise;
89
+ future.resolve();
90
+ }
91
+ catch (e) {
92
+ console.error('Failed to handle image event', e);
93
+ future.reject(e);
94
+ }
95
+ });
80
96
  await queue.addPrompt(aiRequest, conversationId, true);
81
97
  await queue.wait();
82
98
  await Promise.allSettled(promises);
@@ -142,6 +158,8 @@ router.post('/:handle/ui/iterative', async (req, res) => {
142
158
  title: landingPage.title,
143
159
  filename: landingPage.filename,
144
160
  storage_prefix: systemId + '_',
161
+ // TODO: Add themes to this request type
162
+ theme: '',
145
163
  });
146
164
  }
147
165
  catch (e) {
@@ -156,6 +174,18 @@ router.post('/:handle/ui/iterative', async (req, res) => {
156
174
  pageQueue.on('page', (screenData) => {
157
175
  pageEventPromises.push(sendPageEvent(landingPagesStream.getConversationId(), screenData, res));
158
176
  });
177
+ pageQueue.on('image', async (screenData, prompt, future) => {
178
+ try {
179
+ const promise = handleImageEvent(landingPagesStream.getConversationId(), screenData, prompt);
180
+ pageEventPromises.push(promise);
181
+ await promise;
182
+ future.resolve();
183
+ }
184
+ catch (e) {
185
+ console.error('Failed to handle image event', e);
186
+ future.reject(e);
187
+ }
188
+ });
159
189
  pageQueue.on('event', (screenData) => {
160
190
  sendEvent(res, screenData);
161
191
  });
@@ -177,11 +207,10 @@ router.post('/:handle/ui/iterative', async (req, res) => {
177
207
  router.post('/:handle/ui', async (req, res) => {
178
208
  const handle = req.params.handle;
179
209
  try {
180
- const conversationId = req.headers[stormClient_1.ConversationIdHeader.toLowerCase()];
210
+ const outerConversationId = req.headers[stormClient_1.ConversationIdHeader.toLowerCase()] || (0, crypto_1.randomUUID)();
181
211
  const aiRequest = JSON.parse(req.stringBody ?? '{}');
182
212
  // Get user journeys
183
- const userJourneysStream = await stormClient_1.stormClient.createUIUserJourneys(aiRequest, conversationId);
184
- const outerConversationId = userJourneysStream.getConversationId();
213
+ const userJourneysStream = await stormClient_1.stormClient.createUIUserJourneys(aiRequest, outerConversationId);
185
214
  onRequestAborted(req, res, () => {
186
215
  userJourneysStream.abort();
187
216
  });
@@ -213,9 +242,50 @@ router.post('/:handle/ui', async (req, res) => {
213
242
  userJourneysStream.abort();
214
243
  sendError(error, res);
215
244
  });
245
+ let theme = '';
246
+ try {
247
+ const themeStream = await stormClient_1.stormClient.createTheme(aiRequest, outerConversationId);
248
+ onRequestAborted(req, res, () => {
249
+ themeStream.abort();
250
+ });
251
+ themeStream.on('data', (evt) => {
252
+ sendEvent(res, evt);
253
+ if (evt.type === 'FILE_DONE') {
254
+ theme = evt.payload.content;
255
+ (0, page_utils_1.writeAssetToDisk)(outerConversationId, evt).catch((err) => {
256
+ sendEvent(res, {
257
+ type: 'ERROR_INTERNAL',
258
+ created: new Date().getTime(),
259
+ payload: { error: err.message },
260
+ reason: 'Failed to save theme',
261
+ });
262
+ });
263
+ }
264
+ });
265
+ themeStream.on('error', (error) => {
266
+ console.error(error);
267
+ sendEvent(res, {
268
+ type: 'ERROR_INTERNAL',
269
+ created: new Date().getTime(),
270
+ payload: { error: error.message },
271
+ reason: 'Failed to create theme',
272
+ });
273
+ });
274
+ await waitForStormStream(themeStream);
275
+ }
276
+ catch (e) {
277
+ console.error('Failed to generate theme', e);
278
+ sendEvent(res, {
279
+ type: 'ERROR_INTERNAL',
280
+ created: new Date().getTime(),
281
+ payload: { error: e.message },
282
+ reason: 'Failed to create theme',
283
+ });
284
+ }
216
285
  await waitForStormStream(userJourneysStream);
217
286
  // Get the UI shells
218
287
  const shellsStream = await stormClient_1.stormClient.createUIShells({
288
+ theme: theme ? `// filename: theme.css\n${theme}` : undefined,
219
289
  pages: Object.values(uniqueUserJourneyScreens).map((screen) => ({
220
290
  name: screen.name,
221
291
  title: screen.title,
@@ -224,13 +294,14 @@ router.post('/:handle/ui', async (req, res) => {
224
294
  method: screen.method,
225
295
  requirements: screen.requirements,
226
296
  })),
227
- }, conversationId);
297
+ }, outerConversationId);
228
298
  onRequestAborted(req, res, () => {
229
299
  shellsStream.abort();
230
300
  });
231
301
  const queue = new PageGenerator_1.PageQueue(outerConversationId, 5);
302
+ queue.setUiTheme(theme);
232
303
  shellsStream.on('data', (data) => {
233
- console.log('Processing shell event', data);
304
+ //console.log('Processing shell event', data);
234
305
  sendEvent(res, data);
235
306
  if (data.type !== 'UI_SHELL') {
236
307
  return;
@@ -266,6 +337,18 @@ router.post('/:handle/ui', async (req, res) => {
266
337
  queue.on('page', (screenData) => {
267
338
  pageEventPromises.push(sendPageEvent(outerConversationId, screenData, res));
268
339
  });
340
+ queue.on('image', async (screenData, prompt, future) => {
341
+ try {
342
+ const promise = handleImageEvent(outerConversationId, screenData, prompt);
343
+ pageEventPromises.push(promise);
344
+ await promise;
345
+ future.resolve();
346
+ }
347
+ catch (e) {
348
+ console.error('Failed to handle image event', e);
349
+ future.reject(e);
350
+ }
351
+ });
269
352
  queue.on('event', (screenData) => {
270
353
  sendEvent(res, screenData);
271
354
  });
@@ -279,6 +362,7 @@ router.post('/:handle/ui', async (req, res) => {
279
362
  title: screen.title,
280
363
  filename: screen.filename,
281
364
  storage_prefix: outerConversationId + '_',
365
+ theme,
282
366
  }));
283
367
  }
284
368
  await queue.wait();
@@ -580,4 +664,12 @@ async function sendPageEvent(mainConversationId, data, res) {
580
664
  }
581
665
  sendEvent(res, convertPageEvent(data, data.payload.conversationId, mainConversationId));
582
666
  }
667
+ async function handleImageEvent(mainConversationId, data, prompt) {
668
+ try {
669
+ await (0, page_utils_1.writeImageToDisk)(mainConversationId, data, prompt);
670
+ }
671
+ catch (err) {
672
+ console.error('Failed to write image to disk', err);
673
+ }
674
+ }
583
675
  exports.default = router;
@@ -4,6 +4,7 @@ import { Page, StormEventPageUrl } from './events';
4
4
  export declare const STORM_ID = "storm";
5
5
  export declare const ConversationIdHeader = "Conversation-Id";
6
6
  export interface UIShellsPrompt {
7
+ theme?: string;
7
8
  pages: {
8
9
  name: string;
9
10
  title: string;
@@ -23,6 +24,7 @@ export interface UIPagePrompt {
23
24
  description: string;
24
25
  storage_prefix: string;
25
26
  shell_page?: string;
27
+ theme: string;
26
28
  }
27
29
  export interface UIPageSamplePrompt extends UIPagePrompt {
28
30
  variantId: string;
@@ -60,6 +62,7 @@ declare class StormClient {
60
62
  createMetadata(prompt: BasePromptRequest, conversationId?: string): Promise<StormStream>;
61
63
  createUIPages(prompt: string, conversationId?: string): Promise<StormStream>;
62
64
  createUIUserJourneys(prompt: BasePromptRequest, conversationId?: string): Promise<StormStream>;
65
+ createTheme(prompt: BasePromptRequest, conversationId?: string): Promise<StormStream>;
63
66
  createUIShells(prompt: UIShellsPrompt, conversationId?: string): Promise<StormStream>;
64
67
  createUILandingPages(prompt: BasePromptRequest, conversationId?: string): Promise<StormStream>;
65
68
  createUIPage(prompt: UIPagePrompt, conversationId?: string, history?: ConversationItem[]): Promise<StormStream>;
@@ -70,6 +73,7 @@ declare class StormClient {
70
73
  classifyUIReferences(prompt: string, conversationId?: string): Promise<StormStream>;
71
74
  editPages(prompt: UIPageEditPrompt, conversationId?: string): Promise<StormStream>;
72
75
  listScreens(prompt: StormUIListPrompt, conversationId?: string): Promise<StormStream>;
76
+ createImage(prompt: string, conversationId?: string): Promise<StormStream>;
73
77
  createUIImplementation(prompt: StormUIImplementationPrompt, conversationId?: string): Promise<StormStream>;
74
78
  createServiceImplementation(prompt: StormFileImplementationPrompt, conversationId?: string): Promise<StormStream>;
75
79
  createErrorClassification(prompt: string, history?: ConversationItem[], conversationId?: string): Promise<StormStream>;
@@ -92,6 +92,12 @@ class StormClient {
92
92
  conversationId,
93
93
  });
94
94
  }
95
+ createTheme(prompt, conversationId) {
96
+ return this.send('/v2/ui/theme', {
97
+ prompt: prompt,
98
+ conversationId,
99
+ });
100
+ }
95
101
  createUIShells(prompt, conversationId) {
96
102
  return this.send('/v2/ui/shells', {
97
103
  prompt: JSON.stringify(prompt),
@@ -149,6 +155,12 @@ class StormClient {
149
155
  conversationId,
150
156
  });
151
157
  }
158
+ createImage(prompt, conversationId) {
159
+ return this.send('/v2/ui/image', {
160
+ prompt,
161
+ conversationId,
162
+ });
163
+ }
152
164
  createUIImplementation(prompt, conversationId) {
153
165
  return this.send('/v2/ui/merge', {
154
166
  prompt,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kapeta/local-cluster-service",
3
- "version": "0.65.0",
3
+ "version": "0.67.0",
4
4
  "description": "Manages configuration, ports and service discovery for locally running Kapeta systems",
5
5
  "type": "commonjs",
6
6
  "exports": {