@kapeta/local-cluster-service 0.54.3 → 0.54.4
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 +9 -0
- package/dist/cjs/src/storm/codegen.js +36 -18
- package/dist/esm/src/storm/codegen.js +36 -18
- package/package.json +1 -1
- package/src/storm/codegen.ts +40 -23
package/CHANGELOG.md
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
## [0.54.4](https://github.com/kapetacom/local-cluster-service/compare/v0.54.3...v0.54.4) (2024-06-20)
|
2
|
+
|
3
|
+
|
4
|
+
### Bug Fixes
|
5
|
+
|
6
|
+
* merge error ([4c29cab](https://github.com/kapetacom/local-cluster-service/commit/4c29cab33c311a3ad21913b974d92207968a15db))
|
7
|
+
* minors ([c36e825](https://github.com/kapetacom/local-cluster-service/commit/c36e8258cf0d7a3fb0915080f64d524ffd925929))
|
8
|
+
* processTemplate will possibly return a list of files for each file when enhancing services ([3f186a3](https://github.com/kapetacom/local-cluster-service/commit/3f186a3afbb6b527c933ff051d2659e07ab39bbd))
|
9
|
+
|
1
10
|
## [0.54.3](https://github.com/kapetacom/local-cluster-service/compare/v0.54.2...v0.54.3) (2024-06-19)
|
2
11
|
|
3
12
|
|
@@ -117,16 +117,13 @@ class StormCodegen {
|
|
117
117
|
getStream() {
|
118
118
|
return this.out;
|
119
119
|
}
|
120
|
-
handleTemplateFileOutput(blockUri, aiName,
|
120
|
+
handleTemplateFileOutput(blockUri, aiName, data) {
|
121
121
|
if (this.handleFileEvents(blockUri, aiName, data)) {
|
122
122
|
return;
|
123
123
|
}
|
124
124
|
switch (data.type) {
|
125
125
|
case 'FILE_DONE':
|
126
|
-
|
127
|
-
template.content = data.payload.content;
|
128
|
-
this.handleFileDoneOutput(blockUri, aiName, data);
|
129
|
-
break;
|
126
|
+
return this.handleFileDoneOutput(blockUri, aiName, data);
|
130
127
|
}
|
131
128
|
}
|
132
129
|
handleUiOutput(blockUri, blockName, data) {
|
@@ -229,8 +226,10 @@ class StormCodegen {
|
|
229
226
|
if (this.isAborted()) {
|
230
227
|
return;
|
231
228
|
}
|
229
|
+
const kapetaYaml = yaml_1.default.stringify(block.content);
|
230
|
+
const blockDefinition = block.content;
|
232
231
|
// Generate the code for the block using the standard codegen templates
|
233
|
-
const generatedResult = await this.generateBlock(
|
232
|
+
const generatedResult = await this.generateBlock(blockDefinition);
|
234
233
|
if (!generatedResult) {
|
235
234
|
return;
|
236
235
|
}
|
@@ -321,7 +320,7 @@ class StormCodegen {
|
|
321
320
|
if (this.isAborted()) {
|
322
321
|
return;
|
323
322
|
}
|
324
|
-
const basePath = this.getBasePath(
|
323
|
+
const basePath = this.getBasePath(blockDefinition.metadata.name);
|
325
324
|
const screenFilesConverted = screenFiles.map((screenFile) => {
|
326
325
|
return {
|
327
326
|
filename: screenFile.payload.filename,
|
@@ -342,7 +341,7 @@ class StormCodegen {
|
|
342
341
|
};
|
343
342
|
const stream = await stormClient_1.stormClient.generateCode(payload);
|
344
343
|
stream.on('data', (evt) => {
|
345
|
-
this.handleTemplateFileOutput(blockUri, block.aiName,
|
344
|
+
this.handleTemplateFileOutput(blockUri, block.aiName, evt);
|
346
345
|
});
|
347
346
|
this.out.on('aborted', () => {
|
348
347
|
stream.abort();
|
@@ -352,36 +351,37 @@ class StormCodegen {
|
|
352
351
|
// Gather the context files for implementation. These will be all be passed to the AI
|
353
352
|
const contextFiles = relevantFiles.filter((file) => ![codegen_1.AIFileTypes.SERVICE, codegen_1.AIFileTypes.WEB_SCREEN, codegen_1.AIFileTypes.WEB_ROUTER].includes(file.type));
|
354
353
|
// Send the service and UI templates to the AI. These will be sent one-by-one in addition to the context files
|
355
|
-
|
354
|
+
let serviceFiles = allFiles.filter((file) => file.type === codegen_1.AIFileTypes.SERVICE);
|
356
355
|
if (serviceFiles.length > 0) {
|
357
|
-
await this.processTemplates(blockUri, block.aiName, stormClient_1.stormClient.createServiceImplementation.bind(stormClient_1.stormClient), serviceFiles, contextFiles);
|
356
|
+
serviceFiles = await this.processTemplates(blockUri, block.aiName, stormClient_1.stormClient.createServiceImplementation.bind(stormClient_1.stormClient), serviceFiles, contextFiles);
|
358
357
|
}
|
359
358
|
if (this.isAborted()) {
|
360
359
|
return;
|
361
360
|
}
|
361
|
+
for (const contextFile of contextFiles) {
|
362
|
+
const filePath = (0, path_2.join)(basePath, contextFile.filename);
|
363
|
+
await (0, promises_1.writeFile)(filePath, contextFile.content);
|
364
|
+
}
|
362
365
|
for (const screenFile of screenFilesConverted) {
|
363
366
|
const filePath = (0, path_2.join)(basePath, screenFile.filename);
|
364
367
|
await (0, promises_1.writeFile)(filePath, screenFile.content);
|
365
368
|
}
|
369
|
+
// this might decide to overwrite a file that is also a context file
|
366
370
|
for (const serviceFile of serviceFiles) {
|
367
371
|
const filePath = (0, path_2.join)(basePath, serviceFile.filename);
|
368
372
|
await (0, promises_1.writeFile)(filePath, serviceFile.content);
|
369
373
|
}
|
370
|
-
for (const serviceFile of contextFiles) {
|
371
|
-
const filePath = (0, path_2.join)(basePath, serviceFile.filename);
|
372
|
-
await (0, promises_1.writeFile)(filePath, serviceFile.content);
|
373
|
-
}
|
374
374
|
// Write again after modifications
|
375
375
|
for (const webRouterFile of webRouters) {
|
376
376
|
const filePath = (0, path_2.join)(basePath, webRouterFile.filename);
|
377
377
|
await (0, promises_1.writeFile)(filePath, webRouterFile.content);
|
378
378
|
}
|
379
379
|
const kapetaYmlPath = (0, path_2.join)(basePath, 'kapeta.yml');
|
380
|
-
await (0, promises_1.writeFile)(kapetaYmlPath,
|
380
|
+
await (0, promises_1.writeFile)(kapetaYmlPath, kapetaYaml);
|
381
381
|
const blockRef = block.uri;
|
382
382
|
this.emitBlockStatus(blockUri, block.aiName, events_1.StormEventBlockStatusType.QA);
|
383
383
|
const filesToBeFixed = serviceFiles.concat(contextFiles).concat(screenFilesConverted);
|
384
|
-
const codeGenerator = new codegen_1.BlockCodeGenerator(
|
384
|
+
const codeGenerator = new codegen_1.BlockCodeGenerator(blockDefinition);
|
385
385
|
this.emitBlockStatus(blockUri, block.aiName, events_1.StormEventBlockStatusType.BUILDING);
|
386
386
|
await this.verifyAndFixCode(blockUri, block.aiName, codeGenerator, basePath, filesToBeFixed, allFiles);
|
387
387
|
this.out.emit('data', {
|
@@ -676,6 +676,7 @@ class StormCodegen {
|
|
676
676
|
*/
|
677
677
|
async processTemplates(blockUri, aiName, generator, templates, contextFiles) {
|
678
678
|
const promises = templates.map(async (templateFile) => {
|
679
|
+
let changedFiles = [];
|
679
680
|
const stream = await generator({
|
680
681
|
context: contextFiles,
|
681
682
|
template: templateFile,
|
@@ -685,11 +686,28 @@ class StormCodegen {
|
|
685
686
|
stream.abort();
|
686
687
|
});
|
687
688
|
stream.on('data', (evt) => {
|
688
|
-
this.handleTemplateFileOutput(blockUri, aiName,
|
689
|
+
let changedFile = this.handleTemplateFileOutput(blockUri, aiName, evt);
|
690
|
+
if (changedFile) {
|
691
|
+
changedFiles.push(...changedFiles, changedFile);
|
692
|
+
}
|
689
693
|
});
|
690
694
|
await stream.waitForDone();
|
695
|
+
return changedFiles;
|
691
696
|
});
|
692
|
-
await Promise.all(promises);
|
697
|
+
const changedFiles = await Promise.all(promises);
|
698
|
+
let allFiles = templates.concat(contextFiles);
|
699
|
+
let result = [];
|
700
|
+
for (const changedFile of changedFiles.flat()) {
|
701
|
+
const find = allFiles.find((file) => file.filename === changedFile.payload.filename);
|
702
|
+
if (find) {
|
703
|
+
result.push({ type: find.type, filename: find.filename, mode: find.mode, permissions: find.permissions,
|
704
|
+
content: changedFile.payload.content });
|
705
|
+
}
|
706
|
+
else {
|
707
|
+
console.warn("processTemplates: AI changed a file that wasn't in the input [" + changedFile.payload.filename + "]");
|
708
|
+
}
|
709
|
+
}
|
710
|
+
return result;
|
693
711
|
}
|
694
712
|
/**
|
695
713
|
* Converts the generated files to a format that can be sent to the AI
|
@@ -117,16 +117,13 @@ class StormCodegen {
|
|
117
117
|
getStream() {
|
118
118
|
return this.out;
|
119
119
|
}
|
120
|
-
handleTemplateFileOutput(blockUri, aiName,
|
120
|
+
handleTemplateFileOutput(blockUri, aiName, data) {
|
121
121
|
if (this.handleFileEvents(blockUri, aiName, data)) {
|
122
122
|
return;
|
123
123
|
}
|
124
124
|
switch (data.type) {
|
125
125
|
case 'FILE_DONE':
|
126
|
-
|
127
|
-
template.content = data.payload.content;
|
128
|
-
this.handleFileDoneOutput(blockUri, aiName, data);
|
129
|
-
break;
|
126
|
+
return this.handleFileDoneOutput(blockUri, aiName, data);
|
130
127
|
}
|
131
128
|
}
|
132
129
|
handleUiOutput(blockUri, blockName, data) {
|
@@ -229,8 +226,10 @@ class StormCodegen {
|
|
229
226
|
if (this.isAborted()) {
|
230
227
|
return;
|
231
228
|
}
|
229
|
+
const kapetaYaml = yaml_1.default.stringify(block.content);
|
230
|
+
const blockDefinition = block.content;
|
232
231
|
// Generate the code for the block using the standard codegen templates
|
233
|
-
const generatedResult = await this.generateBlock(
|
232
|
+
const generatedResult = await this.generateBlock(blockDefinition);
|
234
233
|
if (!generatedResult) {
|
235
234
|
return;
|
236
235
|
}
|
@@ -321,7 +320,7 @@ class StormCodegen {
|
|
321
320
|
if (this.isAborted()) {
|
322
321
|
return;
|
323
322
|
}
|
324
|
-
const basePath = this.getBasePath(
|
323
|
+
const basePath = this.getBasePath(blockDefinition.metadata.name);
|
325
324
|
const screenFilesConverted = screenFiles.map((screenFile) => {
|
326
325
|
return {
|
327
326
|
filename: screenFile.payload.filename,
|
@@ -342,7 +341,7 @@ class StormCodegen {
|
|
342
341
|
};
|
343
342
|
const stream = await stormClient_1.stormClient.generateCode(payload);
|
344
343
|
stream.on('data', (evt) => {
|
345
|
-
this.handleTemplateFileOutput(blockUri, block.aiName,
|
344
|
+
this.handleTemplateFileOutput(blockUri, block.aiName, evt);
|
346
345
|
});
|
347
346
|
this.out.on('aborted', () => {
|
348
347
|
stream.abort();
|
@@ -352,36 +351,37 @@ class StormCodegen {
|
|
352
351
|
// Gather the context files for implementation. These will be all be passed to the AI
|
353
352
|
const contextFiles = relevantFiles.filter((file) => ![codegen_1.AIFileTypes.SERVICE, codegen_1.AIFileTypes.WEB_SCREEN, codegen_1.AIFileTypes.WEB_ROUTER].includes(file.type));
|
354
353
|
// Send the service and UI templates to the AI. These will be sent one-by-one in addition to the context files
|
355
|
-
|
354
|
+
let serviceFiles = allFiles.filter((file) => file.type === codegen_1.AIFileTypes.SERVICE);
|
356
355
|
if (serviceFiles.length > 0) {
|
357
|
-
await this.processTemplates(blockUri, block.aiName, stormClient_1.stormClient.createServiceImplementation.bind(stormClient_1.stormClient), serviceFiles, contextFiles);
|
356
|
+
serviceFiles = await this.processTemplates(blockUri, block.aiName, stormClient_1.stormClient.createServiceImplementation.bind(stormClient_1.stormClient), serviceFiles, contextFiles);
|
358
357
|
}
|
359
358
|
if (this.isAborted()) {
|
360
359
|
return;
|
361
360
|
}
|
361
|
+
for (const contextFile of contextFiles) {
|
362
|
+
const filePath = (0, path_2.join)(basePath, contextFile.filename);
|
363
|
+
await (0, promises_1.writeFile)(filePath, contextFile.content);
|
364
|
+
}
|
362
365
|
for (const screenFile of screenFilesConverted) {
|
363
366
|
const filePath = (0, path_2.join)(basePath, screenFile.filename);
|
364
367
|
await (0, promises_1.writeFile)(filePath, screenFile.content);
|
365
368
|
}
|
369
|
+
// this might decide to overwrite a file that is also a context file
|
366
370
|
for (const serviceFile of serviceFiles) {
|
367
371
|
const filePath = (0, path_2.join)(basePath, serviceFile.filename);
|
368
372
|
await (0, promises_1.writeFile)(filePath, serviceFile.content);
|
369
373
|
}
|
370
|
-
for (const serviceFile of contextFiles) {
|
371
|
-
const filePath = (0, path_2.join)(basePath, serviceFile.filename);
|
372
|
-
await (0, promises_1.writeFile)(filePath, serviceFile.content);
|
373
|
-
}
|
374
374
|
// Write again after modifications
|
375
375
|
for (const webRouterFile of webRouters) {
|
376
376
|
const filePath = (0, path_2.join)(basePath, webRouterFile.filename);
|
377
377
|
await (0, promises_1.writeFile)(filePath, webRouterFile.content);
|
378
378
|
}
|
379
379
|
const kapetaYmlPath = (0, path_2.join)(basePath, 'kapeta.yml');
|
380
|
-
await (0, promises_1.writeFile)(kapetaYmlPath,
|
380
|
+
await (0, promises_1.writeFile)(kapetaYmlPath, kapetaYaml);
|
381
381
|
const blockRef = block.uri;
|
382
382
|
this.emitBlockStatus(blockUri, block.aiName, events_1.StormEventBlockStatusType.QA);
|
383
383
|
const filesToBeFixed = serviceFiles.concat(contextFiles).concat(screenFilesConverted);
|
384
|
-
const codeGenerator = new codegen_1.BlockCodeGenerator(
|
384
|
+
const codeGenerator = new codegen_1.BlockCodeGenerator(blockDefinition);
|
385
385
|
this.emitBlockStatus(blockUri, block.aiName, events_1.StormEventBlockStatusType.BUILDING);
|
386
386
|
await this.verifyAndFixCode(blockUri, block.aiName, codeGenerator, basePath, filesToBeFixed, allFiles);
|
387
387
|
this.out.emit('data', {
|
@@ -676,6 +676,7 @@ class StormCodegen {
|
|
676
676
|
*/
|
677
677
|
async processTemplates(blockUri, aiName, generator, templates, contextFiles) {
|
678
678
|
const promises = templates.map(async (templateFile) => {
|
679
|
+
let changedFiles = [];
|
679
680
|
const stream = await generator({
|
680
681
|
context: contextFiles,
|
681
682
|
template: templateFile,
|
@@ -685,11 +686,28 @@ class StormCodegen {
|
|
685
686
|
stream.abort();
|
686
687
|
});
|
687
688
|
stream.on('data', (evt) => {
|
688
|
-
this.handleTemplateFileOutput(blockUri, aiName,
|
689
|
+
let changedFile = this.handleTemplateFileOutput(blockUri, aiName, evt);
|
690
|
+
if (changedFile) {
|
691
|
+
changedFiles.push(...changedFiles, changedFile);
|
692
|
+
}
|
689
693
|
});
|
690
694
|
await stream.waitForDone();
|
695
|
+
return changedFiles;
|
691
696
|
});
|
692
|
-
await Promise.all(promises);
|
697
|
+
const changedFiles = await Promise.all(promises);
|
698
|
+
let allFiles = templates.concat(contextFiles);
|
699
|
+
let result = [];
|
700
|
+
for (const changedFile of changedFiles.flat()) {
|
701
|
+
const find = allFiles.find((file) => file.filename === changedFile.payload.filename);
|
702
|
+
if (find) {
|
703
|
+
result.push({ type: find.type, filename: find.filename, mode: find.mode, permissions: find.permissions,
|
704
|
+
content: changedFile.payload.content });
|
705
|
+
}
|
706
|
+
else {
|
707
|
+
console.warn("processTemplates: AI changed a file that wasn't in the input [" + changedFile.payload.filename + "]");
|
708
|
+
}
|
709
|
+
}
|
710
|
+
return result;
|
693
711
|
}
|
694
712
|
/**
|
695
713
|
* Converts the generated files to a format that can be sent to the AI
|
package/package.json
CHANGED
package/src/storm/codegen.ts
CHANGED
@@ -36,7 +36,6 @@ import Path, { join } from 'path';
|
|
36
36
|
import os from 'node:os';
|
37
37
|
import { readFileSync, writeFileSync, existsSync } from 'fs';
|
38
38
|
import YAML from 'yaml';
|
39
|
-
import assert from 'assert';
|
40
39
|
|
41
40
|
type ImplementationGenerator<T = StormFileImplementationPrompt> = (
|
42
41
|
prompt: T,
|
@@ -134,19 +133,15 @@ export class StormCodegen {
|
|
134
133
|
private handleTemplateFileOutput(
|
135
134
|
blockUri: KapetaURI,
|
136
135
|
aiName: string,
|
137
|
-
template: StormFileInfo,
|
138
136
|
data: StormEvent
|
139
|
-
):
|
137
|
+
): StormEventFileDone | undefined {
|
140
138
|
if (this.handleFileEvents(blockUri, aiName, data)) {
|
141
139
|
return;
|
142
140
|
}
|
143
141
|
|
144
142
|
switch (data.type) {
|
145
143
|
case 'FILE_DONE':
|
146
|
-
|
147
|
-
template.content = data.payload.content;
|
148
|
-
this.handleFileDoneOutput(blockUri, aiName, data);
|
149
|
-
break;
|
144
|
+
return this.handleFileDoneOutput(blockUri, aiName, data);
|
150
145
|
}
|
151
146
|
}
|
152
147
|
|
@@ -227,7 +222,7 @@ export class StormCodegen {
|
|
227
222
|
return false;
|
228
223
|
}
|
229
224
|
|
230
|
-
private handleFileDoneOutput(blockUri: KapetaURI, aiName: string, data: StormEvent) {
|
225
|
+
private handleFileDoneOutput(blockUri: KapetaURI, aiName: string, data: StormEvent): StormEventFileDone | undefined {
|
231
226
|
switch (data.type) {
|
232
227
|
case 'FILE_DONE':
|
233
228
|
const ref = blockUri.toNormalizedString();
|
@@ -257,8 +252,12 @@ export class StormCodegen {
|
|
257
252
|
if (this.isAborted()) {
|
258
253
|
return;
|
259
254
|
}
|
255
|
+
|
256
|
+
const kapetaYaml = YAML.stringify(block.content);
|
257
|
+
const blockDefinition = block.content;
|
258
|
+
|
260
259
|
// Generate the code for the block using the standard codegen templates
|
261
|
-
const generatedResult = await this.generateBlock(
|
260
|
+
const generatedResult = await this.generateBlock(blockDefinition);
|
262
261
|
if (!generatedResult) {
|
263
262
|
return;
|
264
263
|
}
|
@@ -374,7 +373,7 @@ export class StormCodegen {
|
|
374
373
|
if (this.isAborted()) {
|
375
374
|
return;
|
376
375
|
}
|
377
|
-
const basePath = this.getBasePath(
|
376
|
+
const basePath = this.getBasePath(blockDefinition.metadata.name);
|
378
377
|
|
379
378
|
const screenFilesConverted = screenFiles.map((screenFile) => {
|
380
379
|
return {
|
@@ -400,7 +399,7 @@ export class StormCodegen {
|
|
400
399
|
const stream = await stormClient.generateCode(payload);
|
401
400
|
|
402
401
|
stream.on('data', (evt) => {
|
403
|
-
this.handleTemplateFileOutput(blockUri, block.aiName,
|
402
|
+
this.handleTemplateFileOutput(blockUri, block.aiName, evt);
|
404
403
|
});
|
405
404
|
|
406
405
|
this.out.on('aborted', () => {
|
@@ -417,9 +416,9 @@ export class StormCodegen {
|
|
417
416
|
);
|
418
417
|
|
419
418
|
// Send the service and UI templates to the AI. These will be sent one-by-one in addition to the context files
|
420
|
-
|
419
|
+
let serviceFiles: StormFileInfo[] = allFiles.filter((file) => file.type === AIFileTypes.SERVICE);
|
421
420
|
if (serviceFiles.length > 0) {
|
422
|
-
await this.processTemplates(
|
421
|
+
serviceFiles = await this.processTemplates(
|
423
422
|
blockUri,
|
424
423
|
block.aiName,
|
425
424
|
stormClient.createServiceImplementation.bind(stormClient),
|
@@ -432,21 +431,22 @@ export class StormCodegen {
|
|
432
431
|
return;
|
433
432
|
}
|
434
433
|
|
434
|
+
for (const contextFile of contextFiles) {
|
435
|
+
const filePath = join(basePath, contextFile.filename);
|
436
|
+
await writeFile(filePath, contextFile.content);
|
437
|
+
}
|
438
|
+
|
435
439
|
for (const screenFile of screenFilesConverted) {
|
436
440
|
const filePath = join(basePath, screenFile.filename);
|
437
441
|
await writeFile(filePath, screenFile.content);
|
438
442
|
}
|
439
443
|
|
444
|
+
// this might decide to overwrite a file that is also a context file
|
440
445
|
for (const serviceFile of serviceFiles) {
|
441
446
|
const filePath = join(basePath, serviceFile.filename);
|
442
447
|
await writeFile(filePath, serviceFile.content);
|
443
448
|
}
|
444
449
|
|
445
|
-
for (const serviceFile of contextFiles) {
|
446
|
-
const filePath = join(basePath, serviceFile.filename);
|
447
|
-
await writeFile(filePath, serviceFile.content);
|
448
|
-
}
|
449
|
-
|
450
450
|
// Write again after modifications
|
451
451
|
for (const webRouterFile of webRouters) {
|
452
452
|
const filePath = join(basePath, webRouterFile.filename);
|
@@ -454,14 +454,14 @@ export class StormCodegen {
|
|
454
454
|
}
|
455
455
|
|
456
456
|
const kapetaYmlPath = join(basePath, 'kapeta.yml');
|
457
|
-
await writeFile(kapetaYmlPath,
|
457
|
+
await writeFile(kapetaYmlPath, kapetaYaml);
|
458
458
|
|
459
459
|
const blockRef = block.uri;
|
460
460
|
|
461
461
|
this.emitBlockStatus(blockUri, block.aiName, StormEventBlockStatusType.QA);
|
462
462
|
|
463
463
|
const filesToBeFixed = serviceFiles.concat(contextFiles).concat(screenFilesConverted);
|
464
|
-
const codeGenerator = new BlockCodeGenerator(
|
464
|
+
const codeGenerator = new BlockCodeGenerator(blockDefinition);
|
465
465
|
|
466
466
|
this.emitBlockStatus(blockUri, block.aiName, StormEventBlockStatusType.BUILDING);
|
467
467
|
await this.verifyAndFixCode(blockUri, block.aiName, codeGenerator, basePath, filesToBeFixed, allFiles);
|
@@ -864,8 +864,9 @@ export class StormCodegen {
|
|
864
864
|
generator: ImplementationGenerator,
|
865
865
|
templates: StormFileInfo[],
|
866
866
|
contextFiles: StormFileInfo[]
|
867
|
-
): Promise<
|
867
|
+
): Promise<StormFileInfo[]> {
|
868
868
|
const promises = templates.map(async (templateFile) => {
|
869
|
+
let changedFiles: StormEventFileDone[] = [];
|
869
870
|
const stream = await generator({
|
870
871
|
context: contextFiles,
|
871
872
|
template: templateFile,
|
@@ -877,13 +878,29 @@ export class StormCodegen {
|
|
877
878
|
});
|
878
879
|
|
879
880
|
stream.on('data', (evt) => {
|
880
|
-
this.handleTemplateFileOutput(blockUri, aiName,
|
881
|
+
let changedFile = this.handleTemplateFileOutput(blockUri, aiName, evt);
|
882
|
+
if (changedFile) {
|
883
|
+
changedFiles.push(...changedFiles, changedFile);
|
884
|
+
}
|
881
885
|
});
|
882
886
|
|
883
887
|
await stream.waitForDone();
|
888
|
+
return changedFiles;
|
884
889
|
});
|
885
890
|
|
886
|
-
await Promise.all(promises);
|
891
|
+
const changedFiles: StormEventFileDone[][] = await Promise.all(promises);
|
892
|
+
let allFiles = templates.concat(contextFiles);
|
893
|
+
let result: StormFileInfo[] = [];
|
894
|
+
for (const changedFile of changedFiles.flat()) {
|
895
|
+
const find = allFiles.find((file) => file.filename === changedFile.payload.filename);
|
896
|
+
if (find) {
|
897
|
+
result.push({ type: find.type, filename: find.filename, mode: find.mode, permissions: find.permissions,
|
898
|
+
content: changedFile.payload.content });
|
899
|
+
} else {
|
900
|
+
console.warn("processTemplates: AI changed a file that wasn't in the input [" + changedFile.payload.filename + "]");
|
901
|
+
}
|
902
|
+
}
|
903
|
+
return result;
|
887
904
|
}
|
888
905
|
|
889
906
|
/**
|