@kapeta/local-cluster-service 0.67.4 → 0.68.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.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,18 @@
1
+ # [0.68.0](https://github.com/kapetacom/local-cluster-service/compare/v0.67.5...v0.68.0) (2024-09-03)
2
+
3
+
4
+ ### Features
5
+
6
+ * Add fallback page to ui server requests ([45bcf5d](https://github.com/kapetacom/local-cluster-service/commit/45bcf5d596ca359a9ddd63512b705ca840a555c8))
7
+
8
+ ## [0.67.5](https://github.com/kapetacom/local-cluster-service/compare/v0.67.4...v0.67.5) (2024-09-02)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * better tracking of async events [CORE-3409] ([5e8f8cd](https://github.com/kapetacom/local-cluster-service/commit/5e8f8cdbe7e714cf0dfb5b0e7cbb8b60f837c2f9))
14
+ * dont generate individual pages when page matches path w/ params ([c3ca35c](https://github.com/kapetacom/local-cluster-service/commit/c3ca35ce56781ca90f3ca1070fee76aa3f5512ab))
15
+
1
16
  ## [0.67.4](https://github.com/kapetacom/local-cluster-service/compare/v0.67.3...v0.67.4) (2024-08-30)
2
17
 
3
18
 
@@ -6,7 +6,6 @@
6
6
  import { UIPagePrompt } from './stormClient';
7
7
  import { ReferenceClassification, StormEvent, StormEventPage, StormImage, UIShell } from './events';
8
8
  import { EventEmitter } from 'node:events';
9
- import { FuturePromise } from './PromiseQueue';
10
9
  export interface ImagePrompt {
11
10
  name: string;
12
11
  description: string;
@@ -21,6 +20,7 @@ type InitialPrompt = Omit<UIPagePrompt, 'shell_page'> & {
21
20
  };
22
21
  export declare class PageQueue extends EventEmitter {
23
22
  private readonly queue;
23
+ private readonly eventQueue;
24
24
  private readonly systemId;
25
25
  private readonly systemPrompt;
26
26
  private readonly references;
@@ -29,12 +29,12 @@ export declare class PageQueue extends EventEmitter {
29
29
  private uiShells;
30
30
  private theme;
31
31
  constructor(systemId: string, systemPrompt: string, concurrency?: number);
32
- on(event: 'event', listener: (data: StormEvent) => void): this;
33
- on(event: 'page', listener: (data: StormEventPage) => void): this;
34
- on(event: 'image', listener: (data: StormImage, source: ImagePrompt, future: FuturePromise<void>) => void): this;
32
+ on(event: 'event', listener: (data: StormEvent) => void | Promise<void>): this;
33
+ on(event: 'page', listener: (data: StormEventPage) => void | Promise<void>): this;
34
+ on(event: 'image', listener: (data: StormImage, source: ImagePrompt) => void | Promise<void>): this;
35
35
  emit(type: 'event', event: StormEvent): boolean;
36
36
  emit(type: 'page', event: StormEventPage): boolean;
37
- emit(type: 'image', event: StormImage, source: ImagePrompt, future: FuturePromise<void>): boolean;
37
+ emit(type: 'image', event: StormImage, source: ImagePrompt): boolean;
38
38
  addUiShell(uiShell: UIShell): void;
39
39
  setUiTheme(theme: string): void;
40
40
  private hasPrompt;
@@ -47,6 +47,7 @@ export declare class PageQueue extends EventEmitter {
47
47
  private addImagePrompt;
48
48
  }
49
49
  export declare class PageGenerator extends EventEmitter {
50
+ private readonly eventQueue;
50
51
  private readonly conversationId;
51
52
  readonly prompt: UIPagePrompt;
52
53
  constructor(prompt: UIPagePrompt, conversationId?: string);
@@ -54,13 +55,11 @@ export declare class PageGenerator extends EventEmitter {
54
55
  on(event: 'page_refs', listener: (data: {
55
56
  event: StormEventPage;
56
57
  references: ReferenceClassification[];
57
- future: FuturePromise<void>;
58
- }) => void): this;
58
+ }) => Promise<void>): this;
59
59
  emit(type: 'event', event: StormEvent): boolean;
60
60
  emit(type: 'page_refs', event: {
61
61
  event: StormEventPage;
62
62
  references: ReferenceClassification[];
63
- future: FuturePromise<void>;
64
63
  }): boolean;
65
64
  generate(): Promise<void>;
66
65
  private resolveReferences;
@@ -15,6 +15,7 @@ const PromiseQueue_1 = require("./PromiseQueue");
15
15
  const page_utils_1 = require("./page-utils");
16
16
  class PageQueue extends node_events_1.EventEmitter {
17
17
  queue;
18
+ eventQueue;
18
19
  systemId;
19
20
  systemPrompt;
20
21
  references = new Map();
@@ -27,9 +28,12 @@ class PageQueue extends node_events_1.EventEmitter {
27
28
  this.systemId = systemId;
28
29
  this.systemPrompt = systemPrompt;
29
30
  this.queue = new PromiseQueue_1.PromiseQueue(concurrency);
31
+ this.eventQueue = new PromiseQueue_1.PromiseQueue(Number.MAX_VALUE);
30
32
  }
31
33
  on(event, listener) {
32
- return super.on(event, listener);
34
+ return super.on(event, (...args) => {
35
+ void this.eventQueue.add(async () => listener(...args));
36
+ });
33
37
  }
34
38
  emit(eventName, ...args) {
35
39
  return super.emit(eventName, ...args);
@@ -56,6 +60,7 @@ class PageQueue extends node_events_1.EventEmitter {
56
60
  //console.log('Ignoring duplicate prompt', initialPrompt.path);
57
61
  return Promise.resolve();
58
62
  }
63
+ console.log('Generating page for', initialPrompt.method, initialPrompt.path);
59
64
  const prompt = {
60
65
  ...initialPrompt,
61
66
  shell_page: this.uiShells.find((shell) => shell.screens.includes(initialPrompt.name))?.content,
@@ -75,7 +80,7 @@ class PageQueue extends node_events_1.EventEmitter {
75
80
  return promptPrefix;
76
81
  }
77
82
  wrapPagePrompt(pagePath, prompt) {
78
- let promptPrefix = this.getPrefix();
83
+ const promptPrefix = this.getPrefix();
79
84
  let promptPostfix = '';
80
85
  if (this.pages.size > 0) {
81
86
  promptPostfix = `\nThe following pages are already implemented:\n`;
@@ -96,10 +101,10 @@ class PageQueue extends node_events_1.EventEmitter {
96
101
  }
97
102
  async addPageGenerator(generator) {
98
103
  generator.on('event', (event) => this.emit('event', event));
99
- generator.on('page_refs', async ({ event, references, future }) => {
104
+ generator.on('page_refs', async ({ event, references }) => {
100
105
  try {
101
106
  const initialPrompts = [];
102
- let promises = references.map(async (reference) => {
107
+ const resourcePromises = references.map(async (reference) => {
103
108
  if (reference.url.startsWith('#') ||
104
109
  reference.url.startsWith('javascript:') ||
105
110
  reference.url.startsWith('http://') ||
@@ -135,8 +140,11 @@ class PageQueue extends node_events_1.EventEmitter {
135
140
  break;
136
141
  }
137
142
  });
138
- await Promise.allSettled(promises);
139
- initialPrompts.forEach((prompt) => {
143
+ // Wait for resources to be generated
144
+ await Promise.allSettled(resourcePromises);
145
+ this.emit('page', event);
146
+ // Emit any new pages after the current page to increase responsiveness
147
+ const newPages = initialPrompts.map((prompt) => {
140
148
  if (!this.hasPrompt(prompt.path)) {
141
149
  this.emit('page', {
142
150
  type: 'PAGE',
@@ -155,21 +163,24 @@ class PageQueue extends node_events_1.EventEmitter {
155
163
  },
156
164
  });
157
165
  }
158
- this.addPrompt(prompt);
166
+ return this.addPrompt(prompt);
159
167
  });
160
- this.emit('page', event);
168
+ await Promise.allSettled(newPages);
161
169
  }
162
- finally {
163
- future.resolve();
170
+ catch (e) {
171
+ console.error('Failed to process event', e);
172
+ throw e;
164
173
  }
165
174
  });
166
175
  return this.queue.add(() => generator.generate());
167
176
  }
168
177
  cancel() {
169
178
  this.queue.cancel();
179
+ this.eventQueue.cancel();
170
180
  }
171
- wait() {
172
- return this.queue.wait();
181
+ async wait() {
182
+ await this.eventQueue.wait();
183
+ await this.queue.wait();
173
184
  }
174
185
  async addImagePrompt(prompt) {
175
186
  if (this.images.has(prompt.url)) {
@@ -180,65 +191,54 @@ class PageQueue extends node_events_1.EventEmitter {
180
191
  const prefix = this.getPrefix();
181
192
  const result = await stormClient_1.stormClient.createImage(prefix + `Create an image for the url "${prompt.url}" with this description: ${prompt.description}`.trim());
182
193
  //console.log('Adding image prompt', prompt);
183
- const futures = [];
184
- result.on('data', async (event) => {
194
+ result.on('data', (event) => {
185
195
  if (event.type === 'IMAGE') {
186
- const future = (0, PromiseQueue_1.createFuture)();
187
- futures.push(future);
188
- this.emit('image', event, prompt, future);
189
- setTimeout(() => {
190
- if (!future.isResolved()) {
191
- console.log('Image prompt timed out', prompt);
192
- future.reject(new Error('Image prompt timed out'));
193
- }
194
- }, 30000);
196
+ this.emit('image', event, prompt);
195
197
  }
196
198
  });
197
199
  await result.waitForDone();
198
- await Promise.allSettled(futures.map((f) => f.promise));
199
200
  }
200
201
  }
201
202
  exports.PageQueue = PageQueue;
202
203
  class PageGenerator extends node_events_1.EventEmitter {
204
+ eventQueue;
203
205
  conversationId;
204
206
  prompt;
205
207
  constructor(prompt, conversationId = node_uuid_1.default.v4()) {
206
208
  super();
207
209
  this.conversationId = conversationId;
208
210
  this.prompt = prompt;
211
+ this.eventQueue = new PromiseQueue_1.PromiseQueue(Number.MAX_VALUE);
209
212
  }
210
213
  on(event, listener) {
211
- return super.on(event, listener);
214
+ return super.on(event, (...args) => {
215
+ void this.eventQueue.add(async () => listener(...args));
216
+ });
212
217
  }
213
218
  emit(eventName, ...args) {
214
219
  return super.emit(eventName, ...args);
215
220
  }
216
221
  async generate() {
217
- return new Promise(async (resolve) => {
218
- const promises = [];
219
- const screenStream = await stormClient_1.stormClient.createUIPage(this.prompt, this.conversationId);
220
- screenStream.on('data', (event) => {
221
- if (event.type === 'PAGE') {
222
- event.payload.conversationId = this.conversationId;
223
- promises.push((async () => {
224
- const references = await this.resolveReferences(event.payload.content);
225
- //console.log('Resolved references for page', references, event.payload);
226
- const future = (0, PromiseQueue_1.createFuture)();
227
- this.emit('page_refs', {
228
- event,
229
- references,
230
- future,
231
- });
232
- await future.promise;
233
- })());
234
- return;
235
- }
236
- this.emit('event', event);
237
- });
238
- await screenStream.waitForDone();
239
- await Promise.all(promises);
240
- resolve();
222
+ const promises = [];
223
+ const screenStream = await stormClient_1.stormClient.createUIPage(this.prompt, this.conversationId);
224
+ screenStream.on('data', (event) => {
225
+ if (event.type === 'PAGE') {
226
+ event.payload.conversationId = this.conversationId;
227
+ promises.push((async () => {
228
+ const references = await this.resolveReferences(event.payload.content);
229
+ //console.log('Resolved references for page', references, event.payload);
230
+ this.emit('page_refs', {
231
+ event,
232
+ references,
233
+ });
234
+ })());
235
+ return;
236
+ }
237
+ this.emit('event', event);
241
238
  });
239
+ await screenStream.waitForDone();
240
+ await Promise.all(promises);
241
+ await this.eventQueue.wait();
242
242
  }
243
243
  async resolveReferences(content) {
244
244
  const referenceStream = await stormClient_1.stormClient.classifyUIReferences(content);
@@ -12,7 +12,7 @@ function normalizePath(path) {
12
12
  return path
13
13
  .replace(/\?.*$/gi, '')
14
14
  .replace(/:[a-z][a-z_]*\b/gi, '*')
15
- .replace(/\{[a-z]+}/gi, '*');
15
+ .replace(/\{[a-z-.]+}/gi, '*');
16
16
  }
17
17
  async function writePageToDisk(systemId, event) {
18
18
  const baseDir = getSystemBaseDir(systemId);
@@ -53,13 +53,8 @@ async function writeImageToDisk(systemId, event, prompt) {
53
53
  }
54
54
  exports.writeImageToDisk = writeImageToDisk;
55
55
  function hasPageOnDisk(systemId, method, path) {
56
- if (!systemId || !method || !path) {
57
- return false;
58
- }
59
- const baseDir = getSystemBaseDir(systemId);
60
- const filePath = getFilePath(method);
61
- const fullPath = path_1.default.join(baseDir, normalizePath(path), filePath);
62
- return fs_extra_1.default.existsSync(fullPath);
56
+ const fullPath = resolveReadPath(systemId, method, path);
57
+ return !!fullPath && fs_extra_1.default.existsSync(fullPath);
63
58
  }
64
59
  exports.hasPageOnDisk = hasPageOnDisk;
65
60
  function getSystemBaseDir(systemId) {
@@ -90,7 +85,7 @@ function resolveReadPath(systemId, path, method) {
90
85
  }
91
86
  const parts = path.split(/\*/g);
92
87
  let currentPath = '';
93
- for (let part in parts) {
88
+ for (let part of parts) {
94
89
  const thisPath = path_1.default.join(currentPath, part);
95
90
  const starPath = path_1.default.join(currentPath, '*');
96
91
  const thisPathDir = path_1.default.join(baseDir, thisPath);
@@ -103,7 +98,6 @@ function resolveReadPath(systemId, path, method) {
103
98
  currentPath = starPath;
104
99
  continue;
105
100
  }
106
- console.log('Path not found', thisPathDir, starPathDir);
107
101
  // Path not found
108
102
  return null;
109
103
  }
@@ -121,15 +115,101 @@ exports.readPageFromDiskAsString = readPageFromDiskAsString;
121
115
  function readPageFromDisk(systemId, path, method, res) {
122
116
  const filePath = resolveReadPath(systemId, path, method);
123
117
  if (!filePath || !fs_extra_1.default.existsSync(filePath)) {
124
- res.status(404).send('Page not found');
118
+ if (method === 'HEAD') {
119
+ // For HEAD requests, only return the status and headers
120
+ res.status(202).set('Retry-After', '3').end();
121
+ }
122
+ else {
123
+ // For GET requests, return the fallback HTML with status 202
124
+ res.status(202).set('Retry-After', '3').send(getFallbackHtml(path, method));
125
+ }
125
126
  return;
126
127
  }
127
128
  res.type(filePath.split('.').pop());
128
129
  const content = fs_extra_1.default.readFileSync(filePath);
129
- res.write(content);
130
- res.end();
130
+ if (method === 'HEAD') {
131
+ // For HEAD requests, just end the response after setting headers
132
+ res.status(200).end();
133
+ }
134
+ else {
135
+ // For GET requests, return the full content
136
+ res.write(content);
137
+ res.end();
138
+ }
131
139
  }
132
140
  exports.readPageFromDisk = readPageFromDisk;
141
+ function getFallbackHtml(path, method) {
142
+ return `
143
+ <!DOCTYPE html>
144
+ <html lang="en">
145
+
146
+ <head>
147
+ <meta charset="UTF-8">
148
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
149
+ <title>Page Not Ready</title>
150
+ <style>
151
+ @import url('https://fonts.googleapis.com/css2?family=Roboto:wght@400;600&display=swap');
152
+
153
+ body {
154
+ margin: 0;
155
+ padding: 0;
156
+ display: flex;
157
+ align-items: center;
158
+ justify-content: center;
159
+ height: 100vh;
160
+ font-family: 'Roboto', sans-serif;
161
+ background: #1E1F20;
162
+ color: white;
163
+ text-align: center;
164
+ }
165
+
166
+ h1 {
167
+ font-size: 2rem;
168
+ font-weight: 600;
169
+ margin-bottom: 1rem;
170
+ }
171
+
172
+ p {
173
+ font-size: 1rem;
174
+ font-weight: 400;
175
+ }
176
+ </style>
177
+ </head>
178
+
179
+ <body>
180
+ <div>
181
+ <h1>Page Not Ready</h1>
182
+ <p>Henrik is still working on this page. Please wait...</p>
183
+ </div>
184
+ <script>
185
+ const checkInterval = 3000;
186
+ function checkPageReady() {
187
+ fetch('${path}', { method: 'HEAD' })
188
+ .then(response => {
189
+ if (response.status === 200) {
190
+ // The page is ready, reload to fetch it
191
+ window.location.reload();
192
+ } else if (response.status === 202) {
193
+ const retryAfter = response.headers.get('Retry-After');
194
+ const retryInterval = retryAfter ? parseInt(retryAfter) * 1000 : 3000;
195
+ setTimeout(checkPageReady, retryInterval);
196
+ } else {
197
+ // Handle other unexpected statuses
198
+ setTimeout(checkPageReady, 3000);
199
+ }
200
+ })
201
+ .catch(error => {
202
+ console.error('Error checking page status:', error);
203
+ setTimeout(checkPageReady, checkInterval);
204
+ });
205
+ }
206
+ setTimeout(checkPageReady, checkInterval);
207
+ </script>
208
+ </body>
209
+
210
+ </html>
211
+ `;
212
+ }
133
213
  function readConversationFromFile(filename) {
134
214
  if (!fs_extra_1.default.existsSync(filename)) {
135
215
  return [];
@@ -74,24 +74,17 @@ router.post('/ui/screen', async (req, res) => {
74
74
  queue.cancel();
75
75
  });
76
76
  const promises = [];
77
- queue.on('page', (data) => {
78
- if (systemId) {
79
- promises.push(sendPageEvent(systemId, data, res));
80
- }
81
- });
82
- queue.on('image', async (screenData, prompt, future) => {
77
+ queue.on('page', (data) => (systemId ? sendPageEvent(systemId, data, res) : undefined));
78
+ queue.on('image', async (screenData, prompt) => {
83
79
  if (!systemId) {
84
80
  return;
85
81
  }
86
82
  try {
87
- const promise = handleImageEvent(systemId, screenData, prompt);
88
- promises.push(promise);
89
- await promise;
90
- future.resolve();
83
+ await handleImageEvent(systemId, screenData, prompt);
91
84
  }
92
85
  catch (e) {
93
86
  console.error('Failed to handle image event', e);
94
- future.reject(e);
87
+ throw e;
95
88
  }
96
89
  });
97
90
  await queue.addPrompt(aiRequest, conversationId, true);
@@ -186,19 +179,14 @@ router.post('/:handle/ui/iterative', async (req, res) => {
186
179
  onRequestAborted(req, res, () => {
187
180
  pageQueue.cancel();
188
181
  });
189
- pageQueue.on('page', (screenData) => {
190
- pageEventPromises.push(sendPageEvent(landingPagesStream.getConversationId(), screenData, res));
191
- });
192
- pageQueue.on('image', async (screenData, prompt, future) => {
182
+ pageQueue.on('page', (screenData) => sendPageEvent(landingPagesStream.getConversationId(), screenData, res));
183
+ pageQueue.on('image', async (screenData, prompt) => {
193
184
  try {
194
- const promise = handleImageEvent(landingPagesStream.getConversationId(), screenData, prompt);
195
- pageEventPromises.push(promise);
196
- await promise;
197
- future.resolve();
185
+ await handleImageEvent(landingPagesStream.getConversationId(), screenData, prompt);
198
186
  }
199
187
  catch (e) {
200
188
  console.error('Failed to handle image event', e);
201
- future.reject(e);
189
+ throw e;
202
190
  }
203
191
  });
204
192
  pageQueue.on('event', (screenData) => {
@@ -346,31 +334,25 @@ router.post('/:handle/ui', async (req, res) => {
346
334
  },
347
335
  created: Date.now(),
348
336
  });
349
- const pagePromises = [];
350
337
  onRequestAborted(req, res, () => {
351
338
  queue.cancel();
352
339
  });
353
- const pageEventPromises = [];
354
- queue.on('page', (screenData) => {
355
- pageEventPromises.push(sendPageEvent(outerConversationId, screenData, res));
356
- });
357
- queue.on('image', async (screenData, prompt, future) => {
340
+ queue.on('page', (screenData) => sendPageEvent(outerConversationId, screenData, res));
341
+ queue.on('image', async (screenData, prompt) => {
358
342
  try {
359
- const promise = handleImageEvent(outerConversationId, screenData, prompt);
360
- pageEventPromises.push(promise);
361
- await promise;
362
- future.resolve();
343
+ await handleImageEvent(outerConversationId, screenData, prompt);
363
344
  }
364
345
  catch (e) {
365
346
  console.error('Failed to handle image event', e);
366
- future.reject(e);
347
+ throw e;
367
348
  }
368
349
  });
369
350
  queue.on('event', (screenData) => {
370
351
  sendEvent(res, screenData);
371
352
  });
372
353
  for (const screen of Object.values(uniqueUserJourneyScreens)) {
373
- pagePromises.push(queue.addPrompt({
354
+ queue
355
+ .addPrompt({
374
356
  prompt: screen.requirements,
375
357
  method: screen.method,
376
358
  path: screen.path,
@@ -380,14 +362,15 @@ router.post('/:handle/ui', async (req, res) => {
380
362
  filename: screen.filename,
381
363
  storage_prefix: outerConversationId + '_',
382
364
  theme,
383
- }));
365
+ })
366
+ .catch((e) => {
367
+ console.error('Failed to generate page for screen %s', screen.name, e);
368
+ });
384
369
  }
385
370
  if (userJourneysStream.isAborted()) {
386
371
  return;
387
372
  }
388
373
  await queue.wait();
389
- await Promise.allSettled(pagePromises);
390
- await Promise.allSettled(pageEventPromises);
391
374
  sendDone(res);
392
375
  }
393
376
  catch (err) {
@@ -6,7 +6,6 @@
6
6
  import { UIPagePrompt } from './stormClient';
7
7
  import { ReferenceClassification, StormEvent, StormEventPage, StormImage, UIShell } from './events';
8
8
  import { EventEmitter } from 'node:events';
9
- import { FuturePromise } from './PromiseQueue';
10
9
  export interface ImagePrompt {
11
10
  name: string;
12
11
  description: string;
@@ -21,6 +20,7 @@ type InitialPrompt = Omit<UIPagePrompt, 'shell_page'> & {
21
20
  };
22
21
  export declare class PageQueue extends EventEmitter {
23
22
  private readonly queue;
23
+ private readonly eventQueue;
24
24
  private readonly systemId;
25
25
  private readonly systemPrompt;
26
26
  private readonly references;
@@ -29,12 +29,12 @@ export declare class PageQueue extends EventEmitter {
29
29
  private uiShells;
30
30
  private theme;
31
31
  constructor(systemId: string, systemPrompt: string, concurrency?: number);
32
- on(event: 'event', listener: (data: StormEvent) => void): this;
33
- on(event: 'page', listener: (data: StormEventPage) => void): this;
34
- on(event: 'image', listener: (data: StormImage, source: ImagePrompt, future: FuturePromise<void>) => void): this;
32
+ on(event: 'event', listener: (data: StormEvent) => void | Promise<void>): this;
33
+ on(event: 'page', listener: (data: StormEventPage) => void | Promise<void>): this;
34
+ on(event: 'image', listener: (data: StormImage, source: ImagePrompt) => void | Promise<void>): this;
35
35
  emit(type: 'event', event: StormEvent): boolean;
36
36
  emit(type: 'page', event: StormEventPage): boolean;
37
- emit(type: 'image', event: StormImage, source: ImagePrompt, future: FuturePromise<void>): boolean;
37
+ emit(type: 'image', event: StormImage, source: ImagePrompt): boolean;
38
38
  addUiShell(uiShell: UIShell): void;
39
39
  setUiTheme(theme: string): void;
40
40
  private hasPrompt;
@@ -47,6 +47,7 @@ export declare class PageQueue extends EventEmitter {
47
47
  private addImagePrompt;
48
48
  }
49
49
  export declare class PageGenerator extends EventEmitter {
50
+ private readonly eventQueue;
50
51
  private readonly conversationId;
51
52
  readonly prompt: UIPagePrompt;
52
53
  constructor(prompt: UIPagePrompt, conversationId?: string);
@@ -54,13 +55,11 @@ export declare class PageGenerator extends EventEmitter {
54
55
  on(event: 'page_refs', listener: (data: {
55
56
  event: StormEventPage;
56
57
  references: ReferenceClassification[];
57
- future: FuturePromise<void>;
58
- }) => void): this;
58
+ }) => Promise<void>): this;
59
59
  emit(type: 'event', event: StormEvent): boolean;
60
60
  emit(type: 'page_refs', event: {
61
61
  event: StormEventPage;
62
62
  references: ReferenceClassification[];
63
- future: FuturePromise<void>;
64
63
  }): boolean;
65
64
  generate(): Promise<void>;
66
65
  private resolveReferences;