@kapeta/local-cluster-service 0.47.0 → 0.47.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 +14 -0
- package/dist/cjs/src/storm/codegen.js +16 -15
- package/dist/cjs/src/storm/event-parser.d.ts +1 -1
- package/dist/cjs/src/storm/event-parser.js +83 -55
- package/dist/cjs/src/storm/events.d.ts +2 -1
- package/dist/cjs/src/storm/stormClient.js +3 -0
- package/dist/cjs/src/storm/stream.d.ts +1 -0
- package/dist/cjs/test/storm/event-parser.test.js +0 -8
- package/dist/esm/src/storm/codegen.js +16 -15
- package/dist/esm/src/storm/event-parser.d.ts +1 -1
- package/dist/esm/src/storm/event-parser.js +83 -55
- package/dist/esm/src/storm/events.d.ts +2 -1
- package/dist/esm/src/storm/stormClient.js +3 -0
- package/dist/esm/src/storm/stream.d.ts +1 -0
- package/dist/esm/test/storm/event-parser.test.js +0 -8
- package/package.json +4 -4
- package/src/storm/codegen.ts +23 -14
- package/src/storm/event-parser.ts +126 -65
- package/src/storm/events.ts +2 -1
- package/src/storm/routes.ts +12 -13
- package/src/storm/stormClient.ts +4 -0
- package/src/storm/stream.ts +1 -0
- package/test/storm/event-parser.test.ts +0 -8
package/CHANGELOG.md
CHANGED
@@ -1,3 +1,17 @@
|
|
1
|
+
## [0.47.2](https://github.com/kapetacom/local-cluster-service/compare/v0.47.1...v0.47.2) (2024-05-30)
|
2
|
+
|
3
|
+
|
4
|
+
### Bug Fixes
|
5
|
+
|
6
|
+
* Prettify kaplang from AI ([#151](https://github.com/kapetacom/local-cluster-service/issues/151)) ([c5afeac](https://github.com/kapetacom/local-cluster-service/commit/c5afeac7dbacdc689e53f5156a612d883f0662b1))
|
7
|
+
|
8
|
+
## [0.47.1](https://github.com/kapetacom/local-cluster-service/compare/v0.47.0...v0.47.1) (2024-05-30)
|
9
|
+
|
10
|
+
|
11
|
+
### Bug Fixes
|
12
|
+
|
13
|
+
* Make UUIDs deterministic to allow cleaner updates ([#150](https://github.com/kapetacom/local-cluster-service/issues/150)) ([0e3bbec](https://github.com/kapetacom/local-cluster-service/commit/0e3bbecb00d52e2cc0f5e0d8adb9953f40e6e253))
|
14
|
+
|
1
15
|
# [0.47.0](https://github.com/kapetacom/local-cluster-service/compare/v0.46.0...v0.47.0) (2024-05-29)
|
2
16
|
|
3
17
|
|
@@ -28,15 +28,15 @@ class StormCodegen {
|
|
28
28
|
getStream() {
|
29
29
|
return this.out;
|
30
30
|
}
|
31
|
-
handleTemplateFileOutput(blockUri, template, data) {
|
31
|
+
handleTemplateFileOutput(blockUri, aiName, template, data) {
|
32
32
|
switch (data.type) {
|
33
33
|
case 'FILE':
|
34
34
|
template.filename = data.payload.filename;
|
35
35
|
template.content = data.payload.content;
|
36
|
-
return this.handleFileOutput(blockUri, data);
|
36
|
+
return this.handleFileOutput(blockUri, aiName, data);
|
37
37
|
}
|
38
38
|
}
|
39
|
-
handleUiOutput(blockUri, data) {
|
39
|
+
handleUiOutput(blockUri, aiName, data) {
|
40
40
|
switch (data.type) {
|
41
41
|
case 'SCREEN':
|
42
42
|
this.out.emit('data', {
|
@@ -45,17 +45,17 @@ class StormCodegen {
|
|
45
45
|
created: Date.now(),
|
46
46
|
payload: {
|
47
47
|
...data.payload,
|
48
|
-
blockName:
|
48
|
+
blockName: aiName,
|
49
49
|
},
|
50
50
|
});
|
51
51
|
case 'FILE':
|
52
|
-
return this.handleFileOutput(blockUri, data);
|
52
|
+
return this.handleFileOutput(blockUri, aiName, data);
|
53
53
|
}
|
54
54
|
}
|
55
|
-
handleFileOutput(blockUri, data) {
|
55
|
+
handleFileOutput(blockUri, aiName, data) {
|
56
56
|
switch (data.type) {
|
57
57
|
case 'FILE':
|
58
|
-
this.emitFile(blockUri, data.payload.filename, data.payload.content, data.reason);
|
58
|
+
this.emitFile(blockUri, aiName, data.payload.filename, data.payload.content, data.reason);
|
59
59
|
return {
|
60
60
|
type: 'FILE',
|
61
61
|
created: Date.now(),
|
@@ -77,7 +77,7 @@ class StormCodegen {
|
|
77
77
|
}
|
78
78
|
const allFiles = this.toStormFiles(generatedResult);
|
79
79
|
// Send all the non-ai files to the stream
|
80
|
-
this.emitFiles(block.uri, allFiles);
|
80
|
+
this.emitFiles(block.uri, block.aiName, allFiles);
|
81
81
|
const relevantFiles = allFiles.filter((file) => file.type !== codegen_1.AIFileTypes.IGNORE && file.type !== codegen_1.AIFileTypes.WEB_SCREEN);
|
82
82
|
const uiTemplates = allFiles.filter((file) => file.type === codegen_1.AIFileTypes.WEB_SCREEN);
|
83
83
|
if (uiTemplates.length > 0) {
|
@@ -89,7 +89,7 @@ class StormCodegen {
|
|
89
89
|
prompt: this.userPrompt,
|
90
90
|
});
|
91
91
|
uiStream.on('data', (evt) => {
|
92
|
-
this.handleUiOutput(block.uri, evt);
|
92
|
+
this.handleUiOutput(block.uri, block.aiName, evt);
|
93
93
|
});
|
94
94
|
await uiStream.waitForDone();
|
95
95
|
}
|
@@ -98,13 +98,13 @@ class StormCodegen {
|
|
98
98
|
// Send the service and UI templates to the AI. These will be send one-by-one in addition to the context files
|
99
99
|
const serviceFiles = allFiles.filter((file) => file.type === codegen_1.AIFileTypes.SERVICE);
|
100
100
|
if (serviceFiles.length > 0) {
|
101
|
-
await this.processTemplates(block.uri, stormClient_1.stormClient.createServiceImplementation.bind(stormClient_1.stormClient), serviceFiles, contextFiles);
|
101
|
+
await this.processTemplates(block.uri, block.aiName, stormClient_1.stormClient.createServiceImplementation.bind(stormClient_1.stormClient), serviceFiles, contextFiles);
|
102
102
|
}
|
103
103
|
}
|
104
104
|
/**
|
105
105
|
* Emits the text-based files to the stream
|
106
106
|
*/
|
107
|
-
emitFiles(uri, files) {
|
107
|
+
emitFiles(uri, aiName, files) {
|
108
108
|
files.forEach((file) => {
|
109
109
|
if (!file.content || typeof file.content !== 'string') {
|
110
110
|
return;
|
@@ -119,10 +119,10 @@ class StormCodegen {
|
|
119
119
|
// They will need to be implemented by the AI
|
120
120
|
return;
|
121
121
|
}
|
122
|
-
this.emitFile(uri, file.filename, file.content);
|
122
|
+
this.emitFile(uri, aiName, file.filename, file.content);
|
123
123
|
});
|
124
124
|
}
|
125
|
-
emitFile(uri, filename, content, reason = 'File generated') {
|
125
|
+
emitFile(uri, blockName, filename, content, reason = 'File generated') {
|
126
126
|
this.out.emit('data', {
|
127
127
|
type: 'FILE',
|
128
128
|
reason,
|
@@ -130,6 +130,7 @@ class StormCodegen {
|
|
130
130
|
payload: {
|
131
131
|
filename: filename,
|
132
132
|
content: content,
|
133
|
+
blockName,
|
133
134
|
blockRef: uri.toNormalizedString(),
|
134
135
|
},
|
135
136
|
});
|
@@ -137,7 +138,7 @@ class StormCodegen {
|
|
137
138
|
/**
|
138
139
|
* Sends the template to the AI and processes the response
|
139
140
|
*/
|
140
|
-
async processTemplates(blockUri, generator, templates, contextFiles) {
|
141
|
+
async processTemplates(blockUri, aiName, generator, templates, contextFiles) {
|
141
142
|
const promises = templates.map(async (templateFile) => {
|
142
143
|
const stream = await generator({
|
143
144
|
context: contextFiles,
|
@@ -146,7 +147,7 @@ class StormCodegen {
|
|
146
147
|
});
|
147
148
|
const files = [];
|
148
149
|
stream.on('data', (evt) => {
|
149
|
-
const file = this.handleTemplateFileOutput(blockUri, templateFile, evt);
|
150
|
+
const file = this.handleTemplateFileOutput(blockUri, aiName, templateFile, evt);
|
150
151
|
if (file) {
|
151
152
|
files.push(file);
|
152
153
|
}
|
@@ -55,7 +55,6 @@ export declare class StormEventParser {
|
|
55
55
|
getEvents(): StormEvent[];
|
56
56
|
isValid(): boolean;
|
57
57
|
getError(): string;
|
58
|
-
private applyLayoutToBlocks;
|
59
58
|
toResult(handle: string): StormDefinitions;
|
60
59
|
private toSafeName;
|
61
60
|
private toRef;
|
@@ -64,6 +63,7 @@ export declare class StormEventParser {
|
|
64
63
|
};
|
65
64
|
private toResourceKind;
|
66
65
|
private toBlockKind;
|
66
|
+
private toConnectionMapping;
|
67
67
|
private toPortType;
|
68
68
|
private toBlockTarget;
|
69
69
|
private toBlockTargetKind;
|
@@ -3,17 +3,32 @@
|
|
3
3
|
* Copyright 2023 Kapeta Inc.
|
4
4
|
* SPDX-License-Identifier: BUSL-1.1
|
5
5
|
*/
|
6
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
7
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
8
|
-
};
|
9
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
10
7
|
exports.StormEventParser = exports.resolveOptions = void 0;
|
11
8
|
const nodejs_utils_1 = require("@kapeta/nodejs-utils");
|
12
9
|
const kaplang_core_1 = require("@kapeta/kaplang-core");
|
13
|
-
const
|
10
|
+
const uuid_1 = require("uuid");
|
14
11
|
const definitionsManager_1 = require("../definitionsManager");
|
15
|
-
|
16
|
-
|
12
|
+
function prettifyKaplang(source) {
|
13
|
+
if (!source || !source.trim()) {
|
14
|
+
return '';
|
15
|
+
}
|
16
|
+
try {
|
17
|
+
const ast = kaplang_core_1.DSLParser.parse(source, {
|
18
|
+
ignoreSemantics: true,
|
19
|
+
types: true,
|
20
|
+
methods: true,
|
21
|
+
rest: true,
|
22
|
+
extends: true,
|
23
|
+
generics: true,
|
24
|
+
});
|
25
|
+
return kaplang_core_1.KaplangWriter.write(ast.entities ?? []);
|
26
|
+
}
|
27
|
+
catch (e) {
|
28
|
+
console.warn('Failed to prettify source:\n%s', source);
|
29
|
+
return source;
|
30
|
+
}
|
31
|
+
}
|
17
32
|
async function resolveOptions() {
|
18
33
|
// Predefined types for now - TODO: Allow user to select / change
|
19
34
|
const blockTypeService = await definitionsManager_1.definitionsManager.getLatestDefinition('kapeta/block-type-service');
|
@@ -89,7 +104,6 @@ async function resolveOptions() {
|
|
89
104
|
};
|
90
105
|
}
|
91
106
|
exports.resolveOptions = resolveOptions;
|
92
|
-
const LAYOUT_MARGIN = 50;
|
93
107
|
class StormEventParser {
|
94
108
|
events = [];
|
95
109
|
planName = '';
|
@@ -110,6 +124,7 @@ class StormEventParser {
|
|
110
124
|
}
|
111
125
|
addEvent(handle, evt) {
|
112
126
|
this.events.push(evt);
|
127
|
+
console.log('evt', evt);
|
113
128
|
switch (evt.type) {
|
114
129
|
case 'CREATE_PLAN_PROPERTIES':
|
115
130
|
this.planName = evt.payload.name;
|
@@ -131,13 +146,13 @@ class StormEventParser {
|
|
131
146
|
this.error = evt.payload.error;
|
132
147
|
break;
|
133
148
|
case 'CREATE_API':
|
134
|
-
this.blocks[evt.payload.blockName].apis.push(evt.payload.content);
|
149
|
+
this.blocks[evt.payload.blockName].apis.push(prettifyKaplang(evt.payload.content));
|
135
150
|
break;
|
136
151
|
case 'CREATE_TYPE':
|
137
|
-
this.blocks[evt.payload.blockName].types.push(evt.payload.content);
|
152
|
+
this.blocks[evt.payload.blockName].types.push(prettifyKaplang(evt.payload.content));
|
138
153
|
break;
|
139
154
|
case 'CREATE_MODEL':
|
140
|
-
this.blocks[evt.payload.blockName].models.push(evt.payload.content);
|
155
|
+
this.blocks[evt.payload.blockName].models.push(prettifyKaplang(evt.payload.content));
|
141
156
|
break;
|
142
157
|
case 'CREATE_CONNECTION':
|
143
158
|
this.connections.push(evt.payload);
|
@@ -153,55 +168,21 @@ class StormEventParser {
|
|
153
168
|
return this.events;
|
154
169
|
}
|
155
170
|
isValid() {
|
171
|
+
if (!this.planName) {
|
172
|
+
return false;
|
173
|
+
}
|
156
174
|
return !this.failed;
|
157
175
|
}
|
158
176
|
getError() {
|
159
177
|
return this.error;
|
160
178
|
}
|
161
|
-
applyLayoutToBlocks(result) {
|
162
|
-
const graph = (0, ngraph_graph_1.default)();
|
163
|
-
const blockInstances = {};
|
164
|
-
result.plan.spec.blocks.forEach((block, index) => {
|
165
|
-
graph.addNode(block.id, block);
|
166
|
-
blockInstances[block.id] = block;
|
167
|
-
});
|
168
|
-
result.plan.spec.connections.forEach((connection) => {
|
169
|
-
graph.addLink(connection.provider.blockId, connection.consumer.blockId);
|
170
|
-
});
|
171
|
-
const layout = (0, ngraph_forcelayout_1.default)(graph, {
|
172
|
-
springLength: 150,
|
173
|
-
debug: true,
|
174
|
-
dimensions: 2,
|
175
|
-
gravity: 2,
|
176
|
-
springCoefficient: 0.0008,
|
177
|
-
});
|
178
|
-
for (let i = 0; i < 100; ++i) {
|
179
|
-
layout.step();
|
180
|
-
}
|
181
|
-
// Layout might place things in negative space. We move everything to positive space
|
182
|
-
const graphBox = layout.getGraphRect();
|
183
|
-
let yAdjust = 0;
|
184
|
-
let xAdjust = 0;
|
185
|
-
if (graphBox.y1 < 0) {
|
186
|
-
yAdjust = -graphBox.y1;
|
187
|
-
}
|
188
|
-
if (graphBox.x1 < 0) {
|
189
|
-
xAdjust = -graphBox.x1;
|
190
|
-
}
|
191
|
-
graph.forEachNode((node) => {
|
192
|
-
const position = layout.getNodePosition(node.id);
|
193
|
-
blockInstances[node.id].dimensions.left = LAYOUT_MARGIN + Math.round(position.x + xAdjust);
|
194
|
-
blockInstances[node.id].dimensions.top = LAYOUT_MARGIN + Math.round(position.y + yAdjust);
|
195
|
-
});
|
196
|
-
layout.dispose();
|
197
|
-
return result;
|
198
|
-
}
|
199
179
|
toResult(handle) {
|
200
|
-
const planRef = this.toRef(handle, this.planName);
|
180
|
+
const planRef = this.toRef(handle, this.planName ?? 'undefined');
|
201
181
|
const blockDefinitions = this.toBlockDefinitions(handle);
|
202
182
|
const refIdMap = {};
|
203
183
|
const blocks = Object.entries(blockDefinitions).map(([ref, block]) => {
|
204
|
-
|
184
|
+
// Create a deterministic uuid
|
185
|
+
const id = (0, uuid_1.v5)(ref, uuid_1.v5.URL);
|
205
186
|
refIdMap[ref] = id;
|
206
187
|
return {
|
207
188
|
id,
|
@@ -249,6 +230,28 @@ class StormEventParser {
|
|
249
230
|
console.warn('Client resource not found: %s on %s', apiConnection.toResource, clientConsumerRef.toNormalizedString(), apiConnection);
|
250
231
|
return;
|
251
232
|
}
|
233
|
+
if (apiProviderBlock.content.spec.entities?.source?.value) {
|
234
|
+
if (!clientConsumerBlock.content.spec.entities) {
|
235
|
+
clientConsumerBlock.content.spec.entities = {
|
236
|
+
types: [],
|
237
|
+
source: {
|
238
|
+
type: kaplang_core_1.KAPLANG_ID,
|
239
|
+
version: kaplang_core_1.KAPLANG_VERSION,
|
240
|
+
value: '',
|
241
|
+
},
|
242
|
+
};
|
243
|
+
}
|
244
|
+
const clientTypes = kaplang_core_1.DSLDataTypeParser.parse(clientConsumerBlock.content.spec.entities.source.value);
|
245
|
+
const apiTypes = kaplang_core_1.DSLDataTypeParser.parse(apiProviderBlock.content.spec.entities?.source?.value);
|
246
|
+
apiTypes.forEach((apiType) => {
|
247
|
+
if (clientTypes.some((clientType) => clientType.name === apiType.name)) {
|
248
|
+
// Already exists
|
249
|
+
return;
|
250
|
+
}
|
251
|
+
clientTypes.push(apiType);
|
252
|
+
});
|
253
|
+
clientConsumerBlock.content.spec.entities.source.value = kaplang_core_1.KaplangWriter.write(clientTypes);
|
254
|
+
}
|
252
255
|
clientResource.spec.methods = apiResource.spec.methods;
|
253
256
|
clientResource.spec.source = apiResource.spec.source;
|
254
257
|
});
|
@@ -267,9 +270,7 @@ class StormEventParser {
|
|
267
270
|
blockId: refIdMap[fromRef.toNormalizedString()],
|
268
271
|
resourceName: connection.fromResource,
|
269
272
|
},
|
270
|
-
mapping:
|
271
|
-
//TODO: Add mapping
|
272
|
-
},
|
273
|
+
mapping: this.toConnectionMapping(handle, connection, blockDefinitions),
|
273
274
|
};
|
274
275
|
});
|
275
276
|
const plan = {
|
@@ -284,10 +285,10 @@ class StormEventParser {
|
|
284
285
|
connections,
|
285
286
|
},
|
286
287
|
};
|
287
|
-
return
|
288
|
+
return {
|
288
289
|
plan,
|
289
290
|
blocks: Object.values(blockDefinitions),
|
290
|
-
}
|
291
|
+
};
|
291
292
|
}
|
292
293
|
toSafeName(name) {
|
293
294
|
return name.toLowerCase().replace(/[^0-9a-z-]/gi, '');
|
@@ -498,6 +499,33 @@ class StormEventParser {
|
|
498
499
|
}
|
499
500
|
return '';
|
500
501
|
}
|
502
|
+
toConnectionMapping(handle, connection, blockDefinitions) {
|
503
|
+
if (connection.fromResourceType !== 'API') {
|
504
|
+
return;
|
505
|
+
}
|
506
|
+
const fromRef = this.toRef(handle, connection.fromComponent);
|
507
|
+
const apiProviderBlock = blockDefinitions[fromRef.toNormalizedString()];
|
508
|
+
if (!apiProviderBlock) {
|
509
|
+
console.warn('Provider block not found: %s', connection.fromComponent, connection);
|
510
|
+
return;
|
511
|
+
}
|
512
|
+
const apiResource = apiProviderBlock.content.spec.providers?.find((p) => p.kind === this.options.apiKind && p.metadata.name === connection.fromResource);
|
513
|
+
if (!apiResource) {
|
514
|
+
console.warn('API resource not found: %s on %s', connection.fromResource, fromRef.toNormalizedString(), connection);
|
515
|
+
return;
|
516
|
+
}
|
517
|
+
const apiMethods = kaplang_core_1.DSLConverters.toSchemaMethods(kaplang_core_1.DSLAPIParser.parse(apiResource.spec?.source?.value ?? '', {
|
518
|
+
ignoreSemantics: true,
|
519
|
+
}));
|
520
|
+
const mapping = {};
|
521
|
+
Object.entries(apiMethods).forEach(([methodId, method]) => {
|
522
|
+
mapping[methodId] = {
|
523
|
+
targetId: methodId,
|
524
|
+
type: 'EXACT',
|
525
|
+
};
|
526
|
+
});
|
527
|
+
return mapping;
|
528
|
+
}
|
501
529
|
toPortType(type) {
|
502
530
|
switch (type) {
|
503
531
|
case 'API':
|
@@ -2,7 +2,7 @@
|
|
2
2
|
* Copyright 2023 Kapeta Inc.
|
3
3
|
* SPDX-License-Identifier: BUSL-1.1
|
4
4
|
*/
|
5
|
-
import { StormDefinitions } from
|
5
|
+
import { StormDefinitions } from './event-parser';
|
6
6
|
export type StormResourceType = 'API' | 'DATABASE' | 'CLIENT' | 'JWTPROVIDER' | 'JWTCONSUMER' | 'WEBFRAGMENT' | 'WEBPAGE' | 'SMTPCLIENT' | 'EXTERNAL_API' | 'SUBSCRIBER' | 'PUBLISHER' | 'QUEUE' | 'EXCHANGE';
|
7
7
|
export type StormBlockType = 'BACKEND' | 'FRONTEND' | 'GATEWAY' | 'MQ' | 'CLI' | 'DESKTOP';
|
8
8
|
export interface StormBlockInfo {
|
@@ -117,6 +117,7 @@ export interface StormEventFile {
|
|
117
117
|
payload: {
|
118
118
|
filename: string;
|
119
119
|
content: string;
|
120
|
+
blockName: string;
|
120
121
|
blockRef: string;
|
121
122
|
};
|
122
123
|
}
|
@@ -28,6 +28,9 @@ class StormClient {
|
|
28
28
|
if (api.hasToken()) {
|
29
29
|
//headers['Authorization'] = `Bearer ${api.getAccessToken()}`; //TODO: Enable authentication
|
30
30
|
}
|
31
|
+
if (body.conversationId) {
|
32
|
+
headers['conversationId'] = body.conversationId;
|
33
|
+
}
|
31
34
|
return {
|
32
35
|
url,
|
33
36
|
method: method,
|
@@ -150,16 +150,8 @@ describe('event-parser', () => {
|
|
150
150
|
expect(dbResource?.spec.source.value).toContain('type Entity');
|
151
151
|
const serviceBlockInstance = result.plan.spec.blocks[0];
|
152
152
|
expect(serviceBlockInstance.name).toBe('service');
|
153
|
-
expect(serviceBlockInstance.dimensions.width).toBe(150);
|
154
|
-
expect(serviceBlockInstance.dimensions.height).toBe(200);
|
155
|
-
expect(serviceBlockInstance.dimensions.top).toBe(3);
|
156
|
-
expect(serviceBlockInstance.dimensions.left).toBe(6);
|
157
153
|
const uiBlockInstance = result.plan.spec.blocks[1];
|
158
154
|
expect(uiBlockInstance.name).toBe('ui');
|
159
|
-
expect(uiBlockInstance.dimensions.width).toBe(150);
|
160
|
-
expect(uiBlockInstance.dimensions.height).toBe(200);
|
161
|
-
expect(uiBlockInstance.dimensions.top).toBe(107);
|
162
|
-
expect(uiBlockInstance.dimensions.left).toBe(112);
|
163
155
|
expect(result.plan.spec.connections.length).toBe(1);
|
164
156
|
expect(result.plan.spec.connections[0].consumer.blockId).toBe(uiBlockInstance.id);
|
165
157
|
expect(result.plan.spec.connections[0].consumer.resourceName).toBe(clientResource?.metadata.name);
|
@@ -28,15 +28,15 @@ class StormCodegen {
|
|
28
28
|
getStream() {
|
29
29
|
return this.out;
|
30
30
|
}
|
31
|
-
handleTemplateFileOutput(blockUri, template, data) {
|
31
|
+
handleTemplateFileOutput(blockUri, aiName, template, data) {
|
32
32
|
switch (data.type) {
|
33
33
|
case 'FILE':
|
34
34
|
template.filename = data.payload.filename;
|
35
35
|
template.content = data.payload.content;
|
36
|
-
return this.handleFileOutput(blockUri, data);
|
36
|
+
return this.handleFileOutput(blockUri, aiName, data);
|
37
37
|
}
|
38
38
|
}
|
39
|
-
handleUiOutput(blockUri, data) {
|
39
|
+
handleUiOutput(blockUri, aiName, data) {
|
40
40
|
switch (data.type) {
|
41
41
|
case 'SCREEN':
|
42
42
|
this.out.emit('data', {
|
@@ -45,17 +45,17 @@ class StormCodegen {
|
|
45
45
|
created: Date.now(),
|
46
46
|
payload: {
|
47
47
|
...data.payload,
|
48
|
-
blockName:
|
48
|
+
blockName: aiName,
|
49
49
|
},
|
50
50
|
});
|
51
51
|
case 'FILE':
|
52
|
-
return this.handleFileOutput(blockUri, data);
|
52
|
+
return this.handleFileOutput(blockUri, aiName, data);
|
53
53
|
}
|
54
54
|
}
|
55
|
-
handleFileOutput(blockUri, data) {
|
55
|
+
handleFileOutput(blockUri, aiName, data) {
|
56
56
|
switch (data.type) {
|
57
57
|
case 'FILE':
|
58
|
-
this.emitFile(blockUri, data.payload.filename, data.payload.content, data.reason);
|
58
|
+
this.emitFile(blockUri, aiName, data.payload.filename, data.payload.content, data.reason);
|
59
59
|
return {
|
60
60
|
type: 'FILE',
|
61
61
|
created: Date.now(),
|
@@ -77,7 +77,7 @@ class StormCodegen {
|
|
77
77
|
}
|
78
78
|
const allFiles = this.toStormFiles(generatedResult);
|
79
79
|
// Send all the non-ai files to the stream
|
80
|
-
this.emitFiles(block.uri, allFiles);
|
80
|
+
this.emitFiles(block.uri, block.aiName, allFiles);
|
81
81
|
const relevantFiles = allFiles.filter((file) => file.type !== codegen_1.AIFileTypes.IGNORE && file.type !== codegen_1.AIFileTypes.WEB_SCREEN);
|
82
82
|
const uiTemplates = allFiles.filter((file) => file.type === codegen_1.AIFileTypes.WEB_SCREEN);
|
83
83
|
if (uiTemplates.length > 0) {
|
@@ -89,7 +89,7 @@ class StormCodegen {
|
|
89
89
|
prompt: this.userPrompt,
|
90
90
|
});
|
91
91
|
uiStream.on('data', (evt) => {
|
92
|
-
this.handleUiOutput(block.uri, evt);
|
92
|
+
this.handleUiOutput(block.uri, block.aiName, evt);
|
93
93
|
});
|
94
94
|
await uiStream.waitForDone();
|
95
95
|
}
|
@@ -98,13 +98,13 @@ class StormCodegen {
|
|
98
98
|
// Send the service and UI templates to the AI. These will be send one-by-one in addition to the context files
|
99
99
|
const serviceFiles = allFiles.filter((file) => file.type === codegen_1.AIFileTypes.SERVICE);
|
100
100
|
if (serviceFiles.length > 0) {
|
101
|
-
await this.processTemplates(block.uri, stormClient_1.stormClient.createServiceImplementation.bind(stormClient_1.stormClient), serviceFiles, contextFiles);
|
101
|
+
await this.processTemplates(block.uri, block.aiName, stormClient_1.stormClient.createServiceImplementation.bind(stormClient_1.stormClient), serviceFiles, contextFiles);
|
102
102
|
}
|
103
103
|
}
|
104
104
|
/**
|
105
105
|
* Emits the text-based files to the stream
|
106
106
|
*/
|
107
|
-
emitFiles(uri, files) {
|
107
|
+
emitFiles(uri, aiName, files) {
|
108
108
|
files.forEach((file) => {
|
109
109
|
if (!file.content || typeof file.content !== 'string') {
|
110
110
|
return;
|
@@ -119,10 +119,10 @@ class StormCodegen {
|
|
119
119
|
// They will need to be implemented by the AI
|
120
120
|
return;
|
121
121
|
}
|
122
|
-
this.emitFile(uri, file.filename, file.content);
|
122
|
+
this.emitFile(uri, aiName, file.filename, file.content);
|
123
123
|
});
|
124
124
|
}
|
125
|
-
emitFile(uri, filename, content, reason = 'File generated') {
|
125
|
+
emitFile(uri, blockName, filename, content, reason = 'File generated') {
|
126
126
|
this.out.emit('data', {
|
127
127
|
type: 'FILE',
|
128
128
|
reason,
|
@@ -130,6 +130,7 @@ class StormCodegen {
|
|
130
130
|
payload: {
|
131
131
|
filename: filename,
|
132
132
|
content: content,
|
133
|
+
blockName,
|
133
134
|
blockRef: uri.toNormalizedString(),
|
134
135
|
},
|
135
136
|
});
|
@@ -137,7 +138,7 @@ class StormCodegen {
|
|
137
138
|
/**
|
138
139
|
* Sends the template to the AI and processes the response
|
139
140
|
*/
|
140
|
-
async processTemplates(blockUri, generator, templates, contextFiles) {
|
141
|
+
async processTemplates(blockUri, aiName, generator, templates, contextFiles) {
|
141
142
|
const promises = templates.map(async (templateFile) => {
|
142
143
|
const stream = await generator({
|
143
144
|
context: contextFiles,
|
@@ -146,7 +147,7 @@ class StormCodegen {
|
|
146
147
|
});
|
147
148
|
const files = [];
|
148
149
|
stream.on('data', (evt) => {
|
149
|
-
const file = this.handleTemplateFileOutput(blockUri, templateFile, evt);
|
150
|
+
const file = this.handleTemplateFileOutput(blockUri, aiName, templateFile, evt);
|
150
151
|
if (file) {
|
151
152
|
files.push(file);
|
152
153
|
}
|
@@ -55,7 +55,6 @@ export declare class StormEventParser {
|
|
55
55
|
getEvents(): StormEvent[];
|
56
56
|
isValid(): boolean;
|
57
57
|
getError(): string;
|
58
|
-
private applyLayoutToBlocks;
|
59
58
|
toResult(handle: string): StormDefinitions;
|
60
59
|
private toSafeName;
|
61
60
|
private toRef;
|
@@ -64,6 +63,7 @@ export declare class StormEventParser {
|
|
64
63
|
};
|
65
64
|
private toResourceKind;
|
66
65
|
private toBlockKind;
|
66
|
+
private toConnectionMapping;
|
67
67
|
private toPortType;
|
68
68
|
private toBlockTarget;
|
69
69
|
private toBlockTargetKind;
|