@kapeta/local-cluster-service 0.51.0 → 0.51.2

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.51.2](https://github.com/kapetacom/local-cluster-service/compare/v0.51.1...v0.51.2) (2024-06-06)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * collect generated screens & write these ([50fa728](https://github.com/kapetacom/local-cluster-service/commit/50fa728fea26c0baad2c37b821602b3ca3c46679))
7
+ * merge errors ([92fae09](https://github.com/kapetacom/local-cluster-service/commit/92fae09bc226e7c6128a0a7ae4123ffe810ebe04))
8
+
9
+ ## [0.51.1](https://github.com/kapetacom/local-cluster-service/compare/v0.51.0...v0.51.1) (2024-06-05)
10
+
11
+
12
+ ### Bug Fixes
13
+
14
+ * Add line numbers to chunks ([a60688e](https://github.com/kapetacom/local-cluster-service/commit/a60688e0341238160c6779ae43cae876a62e622d))
15
+
1
16
  # [0.51.0](https://github.com/kapetacom/local-cluster-service/compare/v0.50.0...v0.51.0) (2024-06-05)
2
17
 
3
18
 
@@ -27,7 +27,6 @@ export declare class StormCodegen {
27
27
  private processBlockCode;
28
28
  private verifyAndFixCode;
29
29
  removePrefix(prefix: string, str: string): string;
30
- writeToFile(fileName: string, code: Promise<string>): Promise<void>;
31
30
  /**
32
31
  * Sends the code to the AI for a fix
33
32
  */
@@ -42,6 +42,7 @@ const path_1 = __importStar(require("path"));
42
42
  const node_os_1 = __importDefault(require("node:os"));
43
43
  const fs_1 = require("fs");
44
44
  const path_2 = __importDefault(require("path"));
45
+ const yaml_1 = __importDefault(require("yaml"));
45
46
  const SIMULATED_DELAY = 1000;
46
47
  class SimulatedFileDelay {
47
48
  file;
@@ -66,6 +67,7 @@ class SimulatedFileDelay {
66
67
  });
67
68
  const lines = this.file.payload.content.split('\n');
68
69
  const delayPerLine = SIMULATED_DELAY / lines.length;
70
+ let lineNumber = 0;
69
71
  for (const line of lines) {
70
72
  await new Promise((resolve) => {
71
73
  setTimeout(() => {
@@ -76,6 +78,7 @@ class SimulatedFileDelay {
76
78
  payload: {
77
79
  ...commonPayload,
78
80
  content: line,
81
+ lineNumber: lineNumber++,
79
82
  },
80
83
  });
81
84
  resolve();
@@ -179,7 +182,7 @@ class StormCodegen {
179
182
  });
180
183
  break;
181
184
  case 'FILE_DONE':
182
- this.handleFileDoneOutput(blockUri, blockName, data);
185
+ return this.handleFileDoneOutput(blockUri, blockName, data);
183
186
  break;
184
187
  }
185
188
  }
@@ -269,6 +272,7 @@ class StormCodegen {
269
272
  }
270
273
  const relevantFiles = allFiles.filter((file) => file.type !== codegen_1.AIFileTypes.IGNORE && file.type !== codegen_1.AIFileTypes.WEB_SCREEN);
271
274
  const uiTemplates = allFiles.filter((file) => file.type === codegen_1.AIFileTypes.WEB_SCREEN);
275
+ const screenFiles = [];
272
276
  if (uiTemplates.length > 0) {
273
277
  const uiStream = await stormClient_1.stormClient.createUIImplementation({
274
278
  events: this.events,
@@ -278,7 +282,10 @@ class StormCodegen {
278
282
  prompt: this.userPrompt,
279
283
  });
280
284
  uiStream.on('data', (evt) => {
281
- this.handleUiOutput((0, nodejs_utils_1.parseKapetaUri)(block.uri), block.aiName, evt);
285
+ const uiFile = this.handleUiOutput((0, nodejs_utils_1.parseKapetaUri)(block.uri), block.aiName, evt);
286
+ if (uiFile != undefined) {
287
+ screenFiles.push(uiFile);
288
+ }
282
289
  });
283
290
  this.out.on('aborted', () => {
284
291
  uiStream.abort();
@@ -307,11 +314,23 @@ class StormCodegen {
307
314
  const filePath = (0, path_1.join)(basePath, serviceFile.filename);
308
315
  await (0, promises_1.writeFile)(filePath, serviceFile.content);
309
316
  }
310
- for (const uiFile of uiTemplates) {
311
- const filePath = (0, path_1.join)(basePath, uiFile.filename);
312
- await (0, promises_1.writeFile)(filePath, uiFile.content);
317
+ const kapetaYmlPath = (0, path_1.join)(basePath, 'kapeta.yml');
318
+ await (0, promises_1.writeFile)(kapetaYmlPath, yaml_1.default.stringify(block.content));
319
+ for (const screenFile of screenFiles) {
320
+ const filePath = (0, path_1.join)(basePath, screenFile.payload.filename);
321
+ await (0, promises_1.writeFile)(filePath, screenFile.payload.content);
313
322
  }
314
- const filesToBeFixed = serviceFiles.concat(contextFiles);
323
+ const screenFilesConverted = screenFiles.map(screenFile => {
324
+ return {
325
+ filename: screenFile.payload.filename,
326
+ content: screenFile.payload.content,
327
+ mode: codegen_1.MODE_CREATE_ONLY,
328
+ permissions: '0644',
329
+ type: codegen_1.AIFileTypes.WEB_SCREEN,
330
+ };
331
+ });
332
+ const filesToBeFixed = serviceFiles.concat(contextFiles).concat(screenFilesConverted);
333
+ allFiles.push(...screenFilesConverted);
315
334
  const codeGenerator = new codegen_1.BlockCodeGenerator(block.content);
316
335
  await this.verifyAndFixCode(codeGenerator, basePath, filesToBeFixed, allFiles);
317
336
  const blockRef = block.uri;
@@ -390,11 +409,6 @@ class StormCodegen {
390
409
  }
391
410
  return str;
392
411
  }
393
- async writeToFile(fileName, code) {
394
- console.log(`writing the fixed code to ${fileName}`);
395
- const resolvedCode = await code;
396
- (0, fs_1.writeFileSync)(fileName, resolvedCode);
397
- }
398
412
  /**
399
413
  * Sends the code to the AI for a fix
400
414
  */
@@ -172,13 +172,19 @@ export interface StormEventFileState extends StormEventFileBase {
172
172
  state: string;
173
173
  };
174
174
  }
175
- export interface StormEventFileContent extends StormEventFileBase {
176
- type: 'FILE_DONE' | 'FILE_CHUNK';
175
+ export interface StormEventFileDone extends StormEventFileBase {
176
+ type: 'FILE_DONE';
177
177
  payload: StormEventFileBasePayload & {
178
178
  content: string;
179
179
  };
180
180
  }
181
- export type StormEventFile = StormEventFileLogical | StormEventFileState | StormEventFileContent;
181
+ export interface StormEventFileChunk extends StormEventFileBase {
182
+ type: 'FILE_CHUNK';
183
+ payload: StormEventFileBasePayload & {
184
+ content: string;
185
+ lineNumber: number;
186
+ };
187
+ }
182
188
  export interface StormEventBlockReady {
183
189
  type: 'BLOCK_READY';
184
190
  reason: string;
@@ -212,4 +218,4 @@ export interface StormEventPhases {
212
218
  phaseType: StormEventPhaseType;
213
219
  };
214
220
  }
215
- export type StormEvent = StormEventCreateBlock | StormEventCreateConnection | StormEventCreatePlanProperties | StormEventInvalidResponse | StormEventPlanRetry | StormEventCreateDSL | StormEventCreateDSLResource | StormEventError | StormEventScreen | StormEventScreenCandidate | StormEventFileLogical | StormEventFileState | StormEventFileContent | StormEventDone | StormEventDefinitionChange | StormEventErrorClassifier | StormEventCodeFix | StormEventBlockReady | StormEventPhases;
221
+ export type StormEvent = StormEventCreateBlock | StormEventCreateConnection | StormEventCreatePlanProperties | StormEventInvalidResponse | StormEventPlanRetry | StormEventCreateDSL | StormEventCreateDSLResource | StormEventError | StormEventScreen | StormEventScreenCandidate | StormEventFileLogical | StormEventFileState | StormEventFileDone | StormEventFileChunk | StormEventDone | StormEventDefinitionChange | StormEventErrorClassifier | StormEventCodeFix | StormEventBlockReady | StormEventPhases;
@@ -20,14 +20,15 @@ class StormClient {
20
20
  constructor() {
21
21
  this._baseUrl = (0, utils_1.getRemoteUrl)('ai-service', 'https://ai.kapeta.com');
22
22
  }
23
- createOptions(path, method, body) {
23
+ async createOptions(path, method, body) {
24
24
  const url = `${this._baseUrl}${path}`;
25
25
  const headers = {
26
26
  'Content-Type': 'application/json',
27
27
  };
28
28
  const api = new nodejs_api_client_1.KapetaAPI();
29
29
  if (api.hasToken()) {
30
- //headers['Authorization'] = `Bearer ${api.getAccessToken()}`; //TODO: Enable authentication
30
+ const token = await api.getAccessToken();
31
+ headers['Authorization'] = `Bearer ${token}`;
31
32
  }
32
33
  if (body.conversationId) {
33
34
  headers[exports.ConversationIdHeader] = body.conversationId;
@@ -42,7 +43,7 @@ class StormClient {
42
43
  }
43
44
  async send(path, body, method = 'POST') {
44
45
  const stringPrompt = typeof body.prompt === 'string' ? body.prompt : JSON.stringify(body.prompt);
45
- const options = this.createOptions(path, method, {
46
+ const options = await this.createOptions(path, method, {
46
47
  prompt: stringPrompt,
47
48
  conversationId: body.conversationId,
48
49
  });
@@ -27,7 +27,6 @@ export declare class StormCodegen {
27
27
  private processBlockCode;
28
28
  private verifyAndFixCode;
29
29
  removePrefix(prefix: string, str: string): string;
30
- writeToFile(fileName: string, code: Promise<string>): Promise<void>;
31
30
  /**
32
31
  * Sends the code to the AI for a fix
33
32
  */
@@ -42,6 +42,7 @@ const path_1 = __importStar(require("path"));
42
42
  const node_os_1 = __importDefault(require("node:os"));
43
43
  const fs_1 = require("fs");
44
44
  const path_2 = __importDefault(require("path"));
45
+ const yaml_1 = __importDefault(require("yaml"));
45
46
  const SIMULATED_DELAY = 1000;
46
47
  class SimulatedFileDelay {
47
48
  file;
@@ -66,6 +67,7 @@ class SimulatedFileDelay {
66
67
  });
67
68
  const lines = this.file.payload.content.split('\n');
68
69
  const delayPerLine = SIMULATED_DELAY / lines.length;
70
+ let lineNumber = 0;
69
71
  for (const line of lines) {
70
72
  await new Promise((resolve) => {
71
73
  setTimeout(() => {
@@ -76,6 +78,7 @@ class SimulatedFileDelay {
76
78
  payload: {
77
79
  ...commonPayload,
78
80
  content: line,
81
+ lineNumber: lineNumber++,
79
82
  },
80
83
  });
81
84
  resolve();
@@ -179,7 +182,7 @@ class StormCodegen {
179
182
  });
180
183
  break;
181
184
  case 'FILE_DONE':
182
- this.handleFileDoneOutput(blockUri, blockName, data);
185
+ return this.handleFileDoneOutput(blockUri, blockName, data);
183
186
  break;
184
187
  }
185
188
  }
@@ -269,6 +272,7 @@ class StormCodegen {
269
272
  }
270
273
  const relevantFiles = allFiles.filter((file) => file.type !== codegen_1.AIFileTypes.IGNORE && file.type !== codegen_1.AIFileTypes.WEB_SCREEN);
271
274
  const uiTemplates = allFiles.filter((file) => file.type === codegen_1.AIFileTypes.WEB_SCREEN);
275
+ const screenFiles = [];
272
276
  if (uiTemplates.length > 0) {
273
277
  const uiStream = await stormClient_1.stormClient.createUIImplementation({
274
278
  events: this.events,
@@ -278,7 +282,10 @@ class StormCodegen {
278
282
  prompt: this.userPrompt,
279
283
  });
280
284
  uiStream.on('data', (evt) => {
281
- this.handleUiOutput((0, nodejs_utils_1.parseKapetaUri)(block.uri), block.aiName, evt);
285
+ const uiFile = this.handleUiOutput((0, nodejs_utils_1.parseKapetaUri)(block.uri), block.aiName, evt);
286
+ if (uiFile != undefined) {
287
+ screenFiles.push(uiFile);
288
+ }
282
289
  });
283
290
  this.out.on('aborted', () => {
284
291
  uiStream.abort();
@@ -307,11 +314,23 @@ class StormCodegen {
307
314
  const filePath = (0, path_1.join)(basePath, serviceFile.filename);
308
315
  await (0, promises_1.writeFile)(filePath, serviceFile.content);
309
316
  }
310
- for (const uiFile of uiTemplates) {
311
- const filePath = (0, path_1.join)(basePath, uiFile.filename);
312
- await (0, promises_1.writeFile)(filePath, uiFile.content);
317
+ const kapetaYmlPath = (0, path_1.join)(basePath, 'kapeta.yml');
318
+ await (0, promises_1.writeFile)(kapetaYmlPath, yaml_1.default.stringify(block.content));
319
+ for (const screenFile of screenFiles) {
320
+ const filePath = (0, path_1.join)(basePath, screenFile.payload.filename);
321
+ await (0, promises_1.writeFile)(filePath, screenFile.payload.content);
313
322
  }
314
- const filesToBeFixed = serviceFiles.concat(contextFiles);
323
+ const screenFilesConverted = screenFiles.map(screenFile => {
324
+ return {
325
+ filename: screenFile.payload.filename,
326
+ content: screenFile.payload.content,
327
+ mode: codegen_1.MODE_CREATE_ONLY,
328
+ permissions: '0644',
329
+ type: codegen_1.AIFileTypes.WEB_SCREEN,
330
+ };
331
+ });
332
+ const filesToBeFixed = serviceFiles.concat(contextFiles).concat(screenFilesConverted);
333
+ allFiles.push(...screenFilesConverted);
315
334
  const codeGenerator = new codegen_1.BlockCodeGenerator(block.content);
316
335
  await this.verifyAndFixCode(codeGenerator, basePath, filesToBeFixed, allFiles);
317
336
  const blockRef = block.uri;
@@ -390,11 +409,6 @@ class StormCodegen {
390
409
  }
391
410
  return str;
392
411
  }
393
- async writeToFile(fileName, code) {
394
- console.log(`writing the fixed code to ${fileName}`);
395
- const resolvedCode = await code;
396
- (0, fs_1.writeFileSync)(fileName, resolvedCode);
397
- }
398
412
  /**
399
413
  * Sends the code to the AI for a fix
400
414
  */
@@ -172,13 +172,19 @@ export interface StormEventFileState extends StormEventFileBase {
172
172
  state: string;
173
173
  };
174
174
  }
175
- export interface StormEventFileContent extends StormEventFileBase {
176
- type: 'FILE_DONE' | 'FILE_CHUNK';
175
+ export interface StormEventFileDone extends StormEventFileBase {
176
+ type: 'FILE_DONE';
177
177
  payload: StormEventFileBasePayload & {
178
178
  content: string;
179
179
  };
180
180
  }
181
- export type StormEventFile = StormEventFileLogical | StormEventFileState | StormEventFileContent;
181
+ export interface StormEventFileChunk extends StormEventFileBase {
182
+ type: 'FILE_CHUNK';
183
+ payload: StormEventFileBasePayload & {
184
+ content: string;
185
+ lineNumber: number;
186
+ };
187
+ }
182
188
  export interface StormEventBlockReady {
183
189
  type: 'BLOCK_READY';
184
190
  reason: string;
@@ -212,4 +218,4 @@ export interface StormEventPhases {
212
218
  phaseType: StormEventPhaseType;
213
219
  };
214
220
  }
215
- export type StormEvent = StormEventCreateBlock | StormEventCreateConnection | StormEventCreatePlanProperties | StormEventInvalidResponse | StormEventPlanRetry | StormEventCreateDSL | StormEventCreateDSLResource | StormEventError | StormEventScreen | StormEventScreenCandidate | StormEventFileLogical | StormEventFileState | StormEventFileContent | StormEventDone | StormEventDefinitionChange | StormEventErrorClassifier | StormEventCodeFix | StormEventBlockReady | StormEventPhases;
221
+ export type StormEvent = StormEventCreateBlock | StormEventCreateConnection | StormEventCreatePlanProperties | StormEventInvalidResponse | StormEventPlanRetry | StormEventCreateDSL | StormEventCreateDSLResource | StormEventError | StormEventScreen | StormEventScreenCandidate | StormEventFileLogical | StormEventFileState | StormEventFileDone | StormEventFileChunk | StormEventDone | StormEventDefinitionChange | StormEventErrorClassifier | StormEventCodeFix | StormEventBlockReady | StormEventPhases;
@@ -20,14 +20,15 @@ class StormClient {
20
20
  constructor() {
21
21
  this._baseUrl = (0, utils_1.getRemoteUrl)('ai-service', 'https://ai.kapeta.com');
22
22
  }
23
- createOptions(path, method, body) {
23
+ async createOptions(path, method, body) {
24
24
  const url = `${this._baseUrl}${path}`;
25
25
  const headers = {
26
26
  'Content-Type': 'application/json',
27
27
  };
28
28
  const api = new nodejs_api_client_1.KapetaAPI();
29
29
  if (api.hasToken()) {
30
- //headers['Authorization'] = `Bearer ${api.getAccessToken()}`; //TODO: Enable authentication
30
+ const token = await api.getAccessToken();
31
+ headers['Authorization'] = `Bearer ${token}`;
31
32
  }
32
33
  if (body.conversationId) {
33
34
  headers[exports.ConversationIdHeader] = body.conversationId;
@@ -42,7 +43,7 @@ class StormClient {
42
43
  }
43
44
  async send(path, body, method = 'POST') {
44
45
  const stringPrompt = typeof body.prompt === 'string' ? body.prompt : JSON.stringify(body.prompt);
45
- const options = this.createOptions(path, method, {
46
+ const options = await this.createOptions(path, method, {
46
47
  prompt: stringPrompt,
47
48
  conversationId: body.conversationId,
48
49
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kapeta/local-cluster-service",
3
- "version": "0.51.0",
3
+ "version": "0.51.2",
4
4
  "description": "Manages configuration, ports and service discovery for locally running Kapeta systems",
5
5
  "type": "commonjs",
6
6
  "exports": {
@@ -11,11 +11,12 @@ import {
11
11
  CodeWriter,
12
12
  GeneratedFile,
13
13
  GeneratedResult,
14
+ MODE_CREATE_ONLY,
14
15
  } from '@kapeta/codegen';
15
16
  import { BlockDefinition } from '@kapeta/schemas';
16
17
  import { codeGeneratorManager } from '../codeGeneratorManager';
17
18
  import { STORM_ID, stormClient } from './stormClient';
18
- import { StormEvent, StormEventFileContent, StormEventFileLogical } from './events';
19
+ import { StormEvent, StormEventFileChunk, StormEventFileDone, StormEventFileLogical } from './events';
19
20
  import { BlockDefinitionInfo, StormEventParser } from './event-parser';
20
21
  import { StormFileImplementationPrompt, StormFileInfo, StormStream } from './stream';
21
22
  import { KapetaURI, parseKapetaUri } from '@kapeta/nodejs-utils';
@@ -24,15 +25,16 @@ import path, { join } from 'path';
24
25
  import os from 'node:os';
25
26
  import { readFile, readFileSync, writeFileSync } from 'fs';
26
27
  import Path from 'path';
28
+ import YAML from "yaml";
27
29
 
28
30
  type ImplementationGenerator = (prompt: StormFileImplementationPrompt, conversationId?: string) => Promise<StormStream>;
29
31
 
30
32
  const SIMULATED_DELAY = 1000;
31
33
 
32
34
  class SimulatedFileDelay {
33
- private readonly file: StormEventFileContent;
35
+ private readonly file: StormEventFileDone;
34
36
  public readonly stream;
35
- constructor(file: StormEventFileContent, stream: StormStream) {
37
+ constructor(file: StormEventFileDone, stream: StormStream) {
36
38
  this.file = file;
37
39
  this.stream = stream;
38
40
  }
@@ -54,6 +56,7 @@ class SimulatedFileDelay {
54
56
 
55
57
  const lines = this.file.payload.content.split('\n');
56
58
  const delayPerLine = SIMULATED_DELAY / lines.length;
59
+ let lineNumber = 0;
57
60
  for (const line of lines) {
58
61
  await new Promise<void>((resolve) => {
59
62
  setTimeout(() => {
@@ -64,8 +67,9 @@ class SimulatedFileDelay {
64
67
  payload: {
65
68
  ...commonPayload,
66
69
  content: line,
70
+ lineNumber: lineNumber++,
67
71
  },
68
- } satisfies StormEventFileContent);
72
+ } satisfies StormEventFileChunk);
69
73
  resolve();
70
74
  }, delayPerLine);
71
75
  });
@@ -126,7 +130,7 @@ export class StormCodegen {
126
130
  }
127
131
  }
128
132
 
129
- private handleUiOutput(blockUri: KapetaURI, blockName: string, data: StormEvent) {
133
+ private handleUiOutput(blockUri: KapetaURI, blockName: string, data: StormEvent): StormEventFileDone | undefined {
130
134
  const blockRef = blockUri.toNormalizedString();
131
135
  const instanceId = StormEventParser.toInstanceIdFromRef(blockRef);
132
136
 
@@ -183,7 +187,7 @@ export class StormCodegen {
183
187
  });
184
188
  break;
185
189
  case 'FILE_DONE':
186
- this.handleFileDoneOutput(blockUri, blockName, data);
190
+ return this.handleFileDoneOutput(blockUri, blockName, data);
187
191
  break;
188
192
  }
189
193
  }
@@ -250,7 +254,7 @@ export class StormCodegen {
250
254
  blockRef: ref,
251
255
  instanceId: StormEventParser.toInstanceIdFromRef(ref),
252
256
  },
253
- } as StormEventFileContent;
257
+ } as StormEventFileDone;
254
258
  }
255
259
  }
256
260
 
@@ -284,6 +288,7 @@ export class StormCodegen {
284
288
  (file) => file.type !== AIFileTypes.IGNORE && file.type !== AIFileTypes.WEB_SCREEN
285
289
  );
286
290
  const uiTemplates: StormFileInfo[] = allFiles.filter((file) => file.type === AIFileTypes.WEB_SCREEN);
291
+ const screenFiles: StormEventFileDone[] = [];
287
292
  if (uiTemplates.length > 0) {
288
293
  const uiStream = await stormClient.createUIImplementation({
289
294
  events: this.events,
@@ -294,7 +299,10 @@ export class StormCodegen {
294
299
  });
295
300
 
296
301
  uiStream.on('data', (evt) => {
297
- this.handleUiOutput(parseKapetaUri(block.uri), block.aiName, evt);
302
+ const uiFile = this.handleUiOutput(parseKapetaUri(block.uri), block.aiName, evt);
303
+ if (uiFile != undefined) {
304
+ screenFiles.push(uiFile);
305
+ }
298
306
  });
299
307
 
300
308
  this.out.on('aborted', () => {
@@ -341,12 +349,25 @@ export class StormCodegen {
341
349
  await writeFile(filePath, serviceFile.content);
342
350
  }
343
351
 
344
- for (const uiFile of uiTemplates) {
345
- const filePath = join(basePath, uiFile.filename);
346
- await writeFile(filePath, uiFile.content);
352
+ const kapetaYmlPath = join(basePath, 'kapeta.yml');
353
+ await writeFile(kapetaYmlPath, YAML.stringify(block.content as BlockDefinition));
354
+
355
+ for (const screenFile of screenFiles) {
356
+ const filePath = join(basePath, screenFile.payload.filename);
357
+ await writeFile(filePath, screenFile.payload.content);
347
358
  }
348
359
 
349
- const filesToBeFixed = serviceFiles.concat(contextFiles);
360
+ const screenFilesConverted = screenFiles.map(screenFile => {
361
+ return {
362
+ filename: screenFile.payload.filename,
363
+ content: screenFile.payload.content,
364
+ mode: MODE_CREATE_ONLY,
365
+ permissions: '0644',
366
+ type: AIFileTypes.WEB_SCREEN,
367
+ };
368
+ });
369
+ const filesToBeFixed = serviceFiles.concat(contextFiles).concat(screenFilesConverted);
370
+ allFiles.push(...screenFilesConverted);
350
371
  const codeGenerator = new BlockCodeGenerator(block.content as BlockDefinition);
351
372
  await this.verifyAndFixCode(codeGenerator, basePath, filesToBeFixed, allFiles);
352
373
 
@@ -437,11 +458,7 @@ export class StormCodegen {
437
458
  }
438
459
  return str;
439
460
  }
440
- async writeToFile(fileName: string, code: Promise<string>) {
441
- console.log(`writing the fixed code to ${fileName}`);
442
- const resolvedCode = await code;
443
- writeFileSync(fileName, resolvedCode);
444
- }
461
+
445
462
  /**
446
463
  * Sends the code to the AI for a fix
447
464
  */
@@ -486,7 +503,7 @@ export class StormCodegen {
486
503
 
487
504
  const basePath = this.getBasePath(uri.fullName);
488
505
  const ref = uri.toNormalizedString();
489
- const fileEvent: StormEventFileContent = {
506
+ const fileEvent: StormEventFileDone = {
490
507
  type: 'FILE_DONE',
491
508
  reason: 'File generated',
492
509
  created: Date.now(),
@@ -526,7 +543,7 @@ export class StormCodegen {
526
543
  blockRef: ref,
527
544
  instanceId: StormEventParser.toInstanceIdFromRef(ref),
528
545
  },
529
- } satisfies StormEventFileContent);
546
+ } satisfies StormEventFileDone);
530
547
  }
531
548
 
532
549
  /**
@@ -208,14 +208,20 @@ export interface StormEventFileState extends StormEventFileBase {
208
208
  };
209
209
  }
210
210
 
211
- export interface StormEventFileContent extends StormEventFileBase {
212
- type: 'FILE_DONE' | 'FILE_CHUNK';
211
+ export interface StormEventFileDone extends StormEventFileBase {
212
+ type: 'FILE_DONE';
213
213
  payload: StormEventFileBasePayload & {
214
214
  content: string;
215
215
  };
216
216
  }
217
217
 
218
- export type StormEventFile = StormEventFileLogical | StormEventFileState | StormEventFileContent;
218
+ export interface StormEventFileChunk extends StormEventFileBase {
219
+ type: 'FILE_CHUNK';
220
+ payload: StormEventFileBasePayload & {
221
+ content: string;
222
+ lineNumber: number;
223
+ };
224
+ }
219
225
 
220
226
  export interface StormEventBlockReady {
221
227
  type: 'BLOCK_READY';
@@ -268,7 +274,8 @@ export type StormEvent =
268
274
  | StormEventScreenCandidate
269
275
  | StormEventFileLogical
270
276
  | StormEventFileState
271
- | StormEventFileContent
277
+ | StormEventFileDone
278
+ | StormEventFileChunk
272
279
  | StormEventDone
273
280
  | StormEventDefinitionChange
274
281
  | StormEventErrorClassifier
@@ -26,14 +26,15 @@ class StormClient {
26
26
  this._baseUrl = getRemoteUrl('ai-service', 'https://ai.kapeta.com');
27
27
  }
28
28
 
29
- private createOptions(path: string, method: string, body: StormContextRequest): RequestInit & { url: string } {
29
+ private async createOptions(path: string, method: string, body: StormContextRequest): Promise<RequestInit & { url: string }> {
30
30
  const url = `${this._baseUrl}${path}`;
31
31
  const headers: { [k: string]: string } = {
32
32
  'Content-Type': 'application/json',
33
33
  };
34
34
  const api = new KapetaAPI();
35
35
  if (api.hasToken()) {
36
- //headers['Authorization'] = `Bearer ${api.getAccessToken()}`; //TODO: Enable authentication
36
+ const token = await api.getAccessToken();
37
+ headers['Authorization'] = `Bearer ${token}`;
37
38
  }
38
39
 
39
40
  if (body.conversationId) {
@@ -56,7 +57,7 @@ class StormClient {
56
57
  ): Promise<StormStream> {
57
58
  const stringPrompt = typeof body.prompt === 'string' ? body.prompt : JSON.stringify(body.prompt);
58
59
 
59
- const options = this.createOptions(path, method, {
60
+ const options = await this.createOptions(path, method, {
60
61
  prompt: stringPrompt,
61
62
  conversationId: body.conversationId,
62
63
  });