@kapeta/local-cluster-service 0.75.0 → 0.76.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 +7 -0
- package/dist/cjs/src/storm/PageGenerator.d.ts +2 -1
- package/dist/cjs/src/storm/PageGenerator.js +5 -3
- package/dist/cjs/src/storm/codegen.d.ts +0 -10
- package/dist/cjs/src/storm/codegen.js +1 -202
- package/dist/cjs/src/storm/routes.js +12 -11
- package/dist/cjs/src/storm/stormClient.d.ts +3 -1
- package/dist/cjs/src/storm/stormClient.js +9 -2
- package/dist/cjs/src/stormService.js +2 -2
- package/dist/esm/src/storm/PageGenerator.d.ts +2 -1
- package/dist/esm/src/storm/PageGenerator.js +5 -3
- package/dist/esm/src/storm/codegen.d.ts +0 -10
- package/dist/esm/src/storm/codegen.js +1 -202
- package/dist/esm/src/storm/routes.js +12 -11
- package/dist/esm/src/storm/stormClient.d.ts +3 -1
- package/dist/esm/src/storm/stormClient.js +9 -2
- package/dist/esm/src/stormService.js +2 -2
- package/package.json +1 -1
- package/src/storm/PageGenerator.ts +5 -3
- package/src/storm/codegen.ts +2 -297
- package/src/storm/routes.ts +12 -11
- package/src/storm/stormClient.ts +8 -1
- package/src/stormService.ts +2 -2
package/src/storm/codegen.ts
CHANGED
@@ -7,7 +7,6 @@ import { Definition } from '@kapeta/local-cluster-config';
|
|
7
7
|
import {
|
8
8
|
AIFileTypes,
|
9
9
|
BlockCodeGenerator,
|
10
|
-
CodeGenerator,
|
11
10
|
CodeWriter,
|
12
11
|
GeneratedFile,
|
13
12
|
GeneratedResult,
|
@@ -21,20 +20,18 @@ import { STORM_ID, StormClient } from './stormClient';
|
|
21
20
|
import {
|
22
21
|
StormEvent,
|
23
22
|
StormEventBlockStatusType,
|
24
|
-
StormEventErrorDetailsFile,
|
25
23
|
StormEventFileChunk,
|
26
24
|
StormEventFileDone,
|
27
25
|
StormEventFileLogical,
|
28
26
|
StormEventScreen,
|
29
27
|
} from './events';
|
30
28
|
import { BlockDefinitionInfo, StormEventParser } from './event-parser';
|
31
|
-
import {
|
29
|
+
import { StormFileImplementationPrompt, StormFileInfo, StormStream } from './stream';
|
32
30
|
import { KapetaURI, parseKapetaUri } from '@kapeta/nodejs-utils';
|
33
31
|
import { writeFile } from 'fs/promises';
|
34
32
|
import path from 'path';
|
35
33
|
import Path, { join } from 'path';
|
36
34
|
import os from 'node:os';
|
37
|
-
import { readFileSync, writeFileSync, existsSync } from 'fs';
|
38
35
|
import YAML from 'yaml';
|
39
36
|
import { PREDEFINED_BLOCKS } from './predefined';
|
40
37
|
import { Archetype } from './archetype';
|
@@ -46,12 +43,6 @@ type ImplementationGenerator<T = StormFileImplementationPrompt> = (
|
|
46
43
|
conversationId?: string
|
47
44
|
) => Promise<StormStream>;
|
48
45
|
|
49
|
-
interface ErrorClassification {
|
50
|
-
error: string;
|
51
|
-
lineNumber: number;
|
52
|
-
column: number;
|
53
|
-
}
|
54
|
-
|
55
46
|
const SIMULATED_DELAY = 1000;
|
56
47
|
const ENABLE_SIMULATED_DELAY = false;
|
57
48
|
class SimulatedFileDelay {
|
@@ -371,7 +362,7 @@ export class StormCodegen {
|
|
371
362
|
});
|
372
363
|
const uiEvents = [];
|
373
364
|
|
374
|
-
const stormClient = new StormClient(this.uiSystemId);
|
365
|
+
const stormClient = new StormClient(blockUri.handle, this.uiSystemId);
|
375
366
|
// generate screens
|
376
367
|
if (uiTemplates.length) {
|
377
368
|
const screenStream = await stormClient.listScreens({
|
@@ -540,249 +531,6 @@ export class StormCodegen {
|
|
540
531
|
} satisfies StormEvent);
|
541
532
|
}
|
542
533
|
|
543
|
-
private async verifyAndFixCode(
|
544
|
-
blockUri: KapetaURI,
|
545
|
-
blockName: string,
|
546
|
-
codeGenerator: CodeGenerator,
|
547
|
-
basePath: string,
|
548
|
-
filesToBeFixed: StormFileInfo[],
|
549
|
-
allFiles: StormFileInfo[]
|
550
|
-
) {
|
551
|
-
let attempts = 0;
|
552
|
-
let validCode = false;
|
553
|
-
for (let i = 0; i <= 3; i++) {
|
554
|
-
attempts++;
|
555
|
-
try {
|
556
|
-
console.log(`Validating the code in ${basePath} attempt #${attempts}`);
|
557
|
-
const result = await codeGenerator.validateForTarget(basePath);
|
558
|
-
if (result && result.valid) {
|
559
|
-
validCode = true;
|
560
|
-
break;
|
561
|
-
}
|
562
|
-
|
563
|
-
if (result && !result.valid) {
|
564
|
-
console.debug('Validation error:', result);
|
565
|
-
|
566
|
-
this.emitBlockStatus(blockUri, blockName, StormEventBlockStatusType.PLANNING_FIX);
|
567
|
-
|
568
|
-
const errors = await this.classifyErrors(result.error, basePath);
|
569
|
-
|
570
|
-
if (errors.size > 0) {
|
571
|
-
this.emitBlockStatus(blockUri, blockName, StormEventBlockStatusType.FIXING);
|
572
|
-
|
573
|
-
const promises = Array.from(errors.entries()).map(([filename, fileErrors]) => {
|
574
|
-
if (filesToBeFixed.some((file) => file.filename === filename)) {
|
575
|
-
return this.tryToFixFile(
|
576
|
-
blockUri,
|
577
|
-
blockName,
|
578
|
-
basePath,
|
579
|
-
filename,
|
580
|
-
fileErrors,
|
581
|
-
allFiles,
|
582
|
-
codeGenerator
|
583
|
-
);
|
584
|
-
}
|
585
|
-
});
|
586
|
-
|
587
|
-
await Promise.all(promises);
|
588
|
-
}
|
589
|
-
|
590
|
-
this.emitBlockStatus(blockUri, blockName, StormEventBlockStatusType.FIX_DONE);
|
591
|
-
}
|
592
|
-
} catch (e) {
|
593
|
-
console.error('Error:', e);
|
594
|
-
}
|
595
|
-
}
|
596
|
-
|
597
|
-
if (validCode) {
|
598
|
-
console.log(`Validation successful after ${attempts} attempts`);
|
599
|
-
} else {
|
600
|
-
console.error(`Validation failed for ${basePath} after ${attempts} attempts`);
|
601
|
-
}
|
602
|
-
}
|
603
|
-
|
604
|
-
private async tryToFixFile(
|
605
|
-
blockUri: KapetaURI,
|
606
|
-
blockName: string,
|
607
|
-
basePath: string,
|
608
|
-
filename: string,
|
609
|
-
fileErrors: ErrorClassification[],
|
610
|
-
allFiles: StormFileInfo[],
|
611
|
-
codeGenerator: CodeGenerator
|
612
|
-
) {
|
613
|
-
console.log(`Processing ${filename}`);
|
614
|
-
const language = await codeGenerator.language();
|
615
|
-
const relevantFiles = allFiles.filter((file) => file.type != AIFileTypes.IGNORE);
|
616
|
-
|
617
|
-
for (let attempts = 1; attempts <= 5; attempts++) {
|
618
|
-
if (fileErrors.length == 0) {
|
619
|
-
console.log(`No more errors for ${filename}`);
|
620
|
-
return;
|
621
|
-
}
|
622
|
-
|
623
|
-
console.log(`Errors in ${filename} - requesting error details`);
|
624
|
-
const filesForContext = await this.getErrorDetailsForFile(
|
625
|
-
basePath,
|
626
|
-
filename,
|
627
|
-
fileErrors[0],
|
628
|
-
relevantFiles,
|
629
|
-
language
|
630
|
-
);
|
631
|
-
console.log(`Get error details for ${filename} requesting code fixes`);
|
632
|
-
|
633
|
-
const fix = this.createFixRequestForFile(
|
634
|
-
basePath,
|
635
|
-
filename,
|
636
|
-
fileErrors[0],
|
637
|
-
filesForContext,
|
638
|
-
relevantFiles,
|
639
|
-
language
|
640
|
-
);
|
641
|
-
const codeFixFile = await this.codeFix(blockUri, blockName, fix);
|
642
|
-
console.log(`Got fixed code for ${filename}`);
|
643
|
-
const filePath =
|
644
|
-
codeFixFile.filename.indexOf(basePath) > -1
|
645
|
-
? codeFixFile.filename
|
646
|
-
: join(basePath, codeFixFile.filename);
|
647
|
-
const existing = readFileSync(filePath);
|
648
|
-
if (
|
649
|
-
existing.toString().replace(/(\r\n|\r|\n)+$/, '') == codeFixFile.content.replace(/(\r\n|\r|\n)+$/, '')
|
650
|
-
) {
|
651
|
-
console.log(`${filename} not changed by gemini`);
|
652
|
-
continue;
|
653
|
-
}
|
654
|
-
writeFileSync(filePath, codeFixFile.content);
|
655
|
-
|
656
|
-
const result = await codeGenerator.validateForTarget(basePath);
|
657
|
-
if (result && result.valid) {
|
658
|
-
return;
|
659
|
-
}
|
660
|
-
|
661
|
-
const errors = await this.classifyErrors(result.error, basePath);
|
662
|
-
fileErrors = errors.get(filename) ?? [];
|
663
|
-
}
|
664
|
-
}
|
665
|
-
|
666
|
-
private async classifyErrors(errors: string, basePath: string): Promise<Map<string, ErrorClassification[]>> {
|
667
|
-
const stormClient = new StormClient(this.uiSystemId);
|
668
|
-
const errorStream = await stormClient.createErrorClassification(errors, []);
|
669
|
-
const fixes = new Map<string, ErrorClassification[]>();
|
670
|
-
|
671
|
-
this.out.on('aborted', () => {
|
672
|
-
errorStream.abort();
|
673
|
-
});
|
674
|
-
|
675
|
-
errorStream.on('data', (evt) => {
|
676
|
-
if (evt.type === 'ERROR_CLASSIFIER') {
|
677
|
-
const eventFileName = this.removePrefix(basePath + '/', evt.payload.filename);
|
678
|
-
const fix = {
|
679
|
-
error: evt.payload.error,
|
680
|
-
lineNumber: evt.payload.lineNumber,
|
681
|
-
column: evt.payload.column,
|
682
|
-
};
|
683
|
-
|
684
|
-
let existingFixes = fixes.get(eventFileName);
|
685
|
-
if (existingFixes) {
|
686
|
-
existingFixes.push(fix);
|
687
|
-
} else {
|
688
|
-
fixes.set(eventFileName, [fix]);
|
689
|
-
}
|
690
|
-
}
|
691
|
-
});
|
692
|
-
|
693
|
-
await errorStream.waitForDone();
|
694
|
-
|
695
|
-
return fixes;
|
696
|
-
}
|
697
|
-
|
698
|
-
private async getErrorDetailsForFile(
|
699
|
-
basePath: string,
|
700
|
-
filename: string,
|
701
|
-
error: ErrorClassification,
|
702
|
-
allFiles: StormFileInfo[],
|
703
|
-
language: string
|
704
|
-
): Promise<string[]> {
|
705
|
-
const filePath = filename.indexOf(basePath) > -1 ? filename : join(basePath, filename); // to compensate when compiler returns absolute path
|
706
|
-
return new Promise<string[]>(async (resolve, reject) => {
|
707
|
-
const request = {
|
708
|
-
language: language,
|
709
|
-
sourceFile: {
|
710
|
-
filename: filename,
|
711
|
-
content: readFileSync(filePath, 'utf8'),
|
712
|
-
},
|
713
|
-
error: error,
|
714
|
-
projectFiles: allFiles.map((f) => f.filename),
|
715
|
-
};
|
716
|
-
const stormClient = new StormClient(this.uiSystemId);
|
717
|
-
const detailsStream = await stormClient.createErrorDetails(JSON.stringify(request), []);
|
718
|
-
detailsStream.on('data', (evt) => {
|
719
|
-
if (evt.type === 'ERROR_DETAILS') {
|
720
|
-
resolve(evt.payload.files);
|
721
|
-
}
|
722
|
-
reject(new Error('Error details: Unexpected event [' + evt.type + ']'));
|
723
|
-
});
|
724
|
-
this.out.on('aborted', () => {
|
725
|
-
detailsStream.abort();
|
726
|
-
reject(new Error('aborted'));
|
727
|
-
});
|
728
|
-
detailsStream.on('error', (err) => {
|
729
|
-
reject(err);
|
730
|
-
});
|
731
|
-
await detailsStream.waitForDone();
|
732
|
-
});
|
733
|
-
}
|
734
|
-
|
735
|
-
private createFixRequestForFile(
|
736
|
-
basePath: string,
|
737
|
-
filename: string,
|
738
|
-
error: ErrorClassification,
|
739
|
-
filesForContext: string[],
|
740
|
-
allFiles: StormFileInfo[],
|
741
|
-
language: string
|
742
|
-
): string {
|
743
|
-
const files = new Set(filesForContext);
|
744
|
-
files.add(filename);
|
745
|
-
|
746
|
-
const requestedFiles = Array.from(files).flatMap((file) => {
|
747
|
-
if (existsSync(file)) {
|
748
|
-
return file;
|
749
|
-
}
|
750
|
-
|
751
|
-
// file does not exist - look for similar
|
752
|
-
const candidateName = file.split('/').pop();
|
753
|
-
return allFiles.filter((file) => file.filename.split('/').pop() === candidateName).map((f) => f.filename);
|
754
|
-
});
|
755
|
-
|
756
|
-
const filePath = filename.indexOf(basePath) > -1 ? filename : join(basePath, filename);
|
757
|
-
const content = readFileSync(filePath, 'utf8');
|
758
|
-
const affectedLine = this.getErrorLine(error, content);
|
759
|
-
|
760
|
-
const fixRequest = {
|
761
|
-
language: language,
|
762
|
-
filename: filename,
|
763
|
-
error: error.error,
|
764
|
-
affectedLine: affectedLine,
|
765
|
-
projectFiles: requestedFiles.map((filename) => {
|
766
|
-
const filePath = filename.indexOf(basePath) > -1 ? filename : join(basePath, filename);
|
767
|
-
const content = readFileSync(filePath, 'utf8');
|
768
|
-
return { filename: filename, content: content };
|
769
|
-
}),
|
770
|
-
};
|
771
|
-
|
772
|
-
return JSON.stringify(fixRequest);
|
773
|
-
}
|
774
|
-
|
775
|
-
private getErrorLine(errorDetails: ErrorClassification, sourceCode: string): string {
|
776
|
-
const lines = sourceCode.split('\n');
|
777
|
-
const errorLine = lines[errorDetails.lineNumber - 1];
|
778
|
-
|
779
|
-
if (!errorLine) {
|
780
|
-
return 'Error: Line number out of range.';
|
781
|
-
}
|
782
|
-
|
783
|
-
return errorLine;
|
784
|
-
}
|
785
|
-
|
786
534
|
removePrefix(prefix: string, str: string): string {
|
787
535
|
if (str.startsWith(prefix)) {
|
788
536
|
return str.slice(prefix.length);
|
@@ -790,49 +538,6 @@ export class StormCodegen {
|
|
790
538
|
return str;
|
791
539
|
}
|
792
540
|
|
793
|
-
/**
|
794
|
-
* Sends the code to the AI for a fix
|
795
|
-
*/
|
796
|
-
private async codeFix(
|
797
|
-
blockUri: KapetaURI,
|
798
|
-
blockName: string,
|
799
|
-
fix: string,
|
800
|
-
history?: ConversationItem[]
|
801
|
-
): Promise<StormEventErrorDetailsFile> {
|
802
|
-
return new Promise<StormEventErrorDetailsFile>(async (resolve, reject) => {
|
803
|
-
try {
|
804
|
-
const stormClient = new StormClient(this.uiSystemId);
|
805
|
-
const fixStream = await stormClient.createCodeFix(fix, history, this.conversationId);
|
806
|
-
let resolved = false;
|
807
|
-
fixStream.on('data', (evt) => {
|
808
|
-
if (this.handleFileEvents(blockUri, blockName, evt)) {
|
809
|
-
return;
|
810
|
-
}
|
811
|
-
this.handleFileDoneOutput(blockUri, blockName, evt);
|
812
|
-
|
813
|
-
if (evt.type === 'CODE_FIX') {
|
814
|
-
resolved = true;
|
815
|
-
resolve(evt.payload);
|
816
|
-
}
|
817
|
-
});
|
818
|
-
this.out.on('aborted', () => {
|
819
|
-
fixStream.abort();
|
820
|
-
reject(new Error('aborted'));
|
821
|
-
});
|
822
|
-
fixStream.on('error', (err) => {
|
823
|
-
reject(err);
|
824
|
-
});
|
825
|
-
fixStream.on('end', () => {
|
826
|
-
if (!resolved) {
|
827
|
-
reject(new Error('Code fix never returned a valid event'));
|
828
|
-
}
|
829
|
-
});
|
830
|
-
} catch (e) {
|
831
|
-
reject(e);
|
832
|
-
}
|
833
|
-
});
|
834
|
-
}
|
835
|
-
|
836
541
|
/**
|
837
542
|
* Emits the text-based files to the stream
|
838
543
|
*/
|
package/src/storm/routes.ts
CHANGED
@@ -152,6 +152,7 @@ router.post('/ui/conversations/:systemId/append', async (req: KapetaBodyRequest,
|
|
152
152
|
|
153
153
|
router.post('/ui/create-system/:handle/:systemId', async (req: KapetaBodyRequest, res: Response) => {
|
154
154
|
const systemId = req.params.systemId as string;
|
155
|
+
const handle = req.params.handle as string;
|
155
156
|
const srcDir = getSystemBaseDir(systemId);
|
156
157
|
const destDir = getSystemBaseImplDir(systemId);
|
157
158
|
|
@@ -162,7 +163,7 @@ router.post('/ui/create-system/:handle/:systemId', async (req: KapetaBodyRequest
|
|
162
163
|
sendEvent(res, createPhaseStartEvent(StormEventPhaseType.IMPLEMENT_APIS));
|
163
164
|
|
164
165
|
const pagesFromDisk = readFilesAndContent(srcDir);
|
165
|
-
const client = new StormClient(systemId)
|
166
|
+
const client = new StormClient(handle, systemId)
|
166
167
|
const pagesWithImplementation = await client.replaceMockWithAPICall({
|
167
168
|
pages: pagesFromDisk,
|
168
169
|
systemId: systemId,
|
@@ -206,7 +207,7 @@ router.post('/ui/create-system-simple/:handle/:systemId', async (req: KapetaBody
|
|
206
207
|
//res.set(ConversationIdHeader, systemId);
|
207
208
|
|
208
209
|
//sendEvent(res, createPhaseStartEvent(StormEventPhaseType.IMPLEMENT_APIS));
|
209
|
-
const client = new StormClient(systemId);
|
210
|
+
const client = new StormClient(handle, systemId);
|
210
211
|
try {
|
211
212
|
const pagesFromDisk = readFilesAndContent(srcDir);
|
212
213
|
const pagesWithImplementation = await client.replaceMockWithAPICall({
|
@@ -306,7 +307,7 @@ router.post('/ui/screen', async (req: KapetaBodyRequest, res: Response) => {
|
|
306
307
|
|
307
308
|
const parentConversationId = systemId ?? '';
|
308
309
|
|
309
|
-
const queue = new PageQueue(parentConversationId, '', 5);
|
310
|
+
const queue = new PageQueue("", parentConversationId, '', 5);
|
310
311
|
onRequestAborted(req, res, () => {
|
311
312
|
queue.cancel();
|
312
313
|
});
|
@@ -348,7 +349,7 @@ router.post('/:handle/ui/iterative', async (req: KapetaBodyRequest, res: Respons
|
|
348
349
|
const conversationId = req.headers[ConversationIdHeader.toLowerCase()] as string | undefined;
|
349
350
|
|
350
351
|
const aiRequest: BasePromptRequest = JSON.parse(req.stringBody ?? '{}');
|
351
|
-
const client = new StormClient(conversationId); //todo is this correct we are using the landing page getConversationId down below as well
|
352
|
+
const client = new StormClient(handle, conversationId); //todo is this correct we are using the landing page getConversationId down below as well
|
352
353
|
const landingPagesStream = await client.createUILandingPages(aiRequest, conversationId);
|
353
354
|
|
354
355
|
onRequestAborted(req, res, () => {
|
@@ -411,7 +412,7 @@ router.post('/:handle/ui/iterative', async (req: KapetaBodyRequest, res: Respons
|
|
411
412
|
systemPrompt.resolve(aiRequest.prompt);
|
412
413
|
});
|
413
414
|
|
414
|
-
const pageQueue = new PageQueue(systemId, await systemPrompt.promise, 5);
|
415
|
+
const pageQueue = new PageQueue(handle, systemId, await systemPrompt.promise, 5);
|
415
416
|
onRequestAborted(req, res, () => {
|
416
417
|
pageQueue.cancel();
|
417
418
|
});
|
@@ -457,7 +458,7 @@ router.post('/:handle/ui', async (req: KapetaBodyRequest, res: Response) => {
|
|
457
458
|
(req.headers[ConversationIdHeader.toLowerCase()] as string | undefined) || randomUUID();
|
458
459
|
|
459
460
|
const aiRequest: BasePromptRequest = JSON.parse(req.stringBody ?? '{}');
|
460
|
-
const stormClient = new StormClient(outerConversationId);
|
461
|
+
const stormClient = new StormClient(handle, outerConversationId);
|
461
462
|
// Get user journeys
|
462
463
|
const userJourneysStream = await stormClient.createUIUserJourneys(aiRequest, outerConversationId);
|
463
464
|
|
@@ -572,7 +573,7 @@ router.post('/:handle/ui', async (req: KapetaBodyRequest, res: Response) => {
|
|
572
573
|
shellsStream.abort();
|
573
574
|
});
|
574
575
|
|
575
|
-
const queue = new PageQueue(outerConversationId, systemPrompt, 5);
|
576
|
+
const queue = new PageQueue(handle, outerConversationId, systemPrompt, 5);
|
576
577
|
queue.setUiTheme(theme);
|
577
578
|
|
578
579
|
shellsStream.on('data', (data: StormEvent) => {
|
@@ -679,7 +680,7 @@ router.post('/ui/edit', async (req: KapetaBodyRequest, res: Response) => {
|
|
679
680
|
const aiRequest: StormContextRequest<UIPageEditRequest> = JSON.parse(req.stringBody ?? '{}');
|
680
681
|
const storagePrefix = systemId ? systemId + '_' : 'mock_';
|
681
682
|
|
682
|
-
const queue = new PageQueue(systemId!, '', 5);
|
683
|
+
const queue = new PageQueue("",systemId!, '', 5);
|
683
684
|
|
684
685
|
onRequestAborted(req, res, () => {
|
685
686
|
queue.cancel();
|
@@ -753,7 +754,7 @@ router.post('/ui/vote', async (req: KapetaBodyRequest, res: Response) => {
|
|
753
754
|
const aiRequest: UIPageVoteRequest = JSON.parse(req.stringBody ?? '{}');
|
754
755
|
const { topic, vote, mainConversationId } = aiRequest;
|
755
756
|
try {
|
756
|
-
const stormClient = new StormClient(mainConversationId);
|
757
|
+
const stormClient = new StormClient("", mainConversationId);
|
757
758
|
await stormClient.voteUIPage(topic, conversationId, vote, mainConversationId);
|
758
759
|
} catch (e: any) {
|
759
760
|
res.status(500).send({ error: e.message });
|
@@ -765,7 +766,7 @@ router.post('/ui/get-vote', async (req: KapetaBodyRequest, res: Response) => {
|
|
765
766
|
const aiRequest: UIPageGetVoteRequest = JSON.parse(req.stringBody ?? '{}');
|
766
767
|
const { topic, mainConversationId } = aiRequest;
|
767
768
|
try {
|
768
|
-
const stormClient = new StormClient(mainConversationId);
|
769
|
+
const stormClient = new StormClient("", mainConversationId);
|
769
770
|
const vote = await stormClient.getVoteUIPage(topic, conversationId, mainConversationId);
|
770
771
|
res.send({ vote });
|
771
772
|
} catch (e: any) {
|
@@ -797,7 +798,7 @@ async function handleAll(req: KapetaBodyRequest, res: Response) {
|
|
797
798
|
const conversationId = req.headers[ConversationIdHeader.toLowerCase()] as string | undefined;
|
798
799
|
|
799
800
|
const aiRequest: BasePromptRequest = JSON.parse(req.stringBody ?? '{}');
|
800
|
-
const stormClient = new StormClient(systemId);
|
801
|
+
const stormClient = new StormClient(handle, systemId);
|
801
802
|
const metaStream = await stormClient.createMetadata(aiRequest, conversationId);
|
802
803
|
|
803
804
|
onRequestAborted(req, res, () => {
|
package/src/storm/stormClient.ts
CHANGED
@@ -25,6 +25,7 @@ export const STORM_ID = 'storm';
|
|
25
25
|
|
26
26
|
export const ConversationIdHeader = 'Conversation-Id';
|
27
27
|
export const SystemIdHeader = 'System-Id';
|
28
|
+
export const HandleHeader = 'Handle';
|
28
29
|
|
29
30
|
export interface UIShellsPrompt {
|
30
31
|
theme?: string;
|
@@ -89,9 +90,11 @@ export interface BasePromptRequest {
|
|
89
90
|
export class StormClient {
|
90
91
|
private readonly _baseUrl: string;
|
91
92
|
private readonly _systemId: string;
|
92
|
-
|
93
|
+
private readonly _handle: string;
|
94
|
+
constructor(handle: string, systemId?: string) {
|
93
95
|
this._baseUrl = getRemoteUrl('ai-service', 'https://ai.kapeta.com');
|
94
96
|
this._systemId = systemId || "";
|
97
|
+
this._handle = handle;
|
95
98
|
}
|
96
99
|
|
97
100
|
private async createOptions(
|
@@ -115,6 +118,9 @@ export class StormClient {
|
|
115
118
|
if (this._systemId) {
|
116
119
|
headers[SystemIdHeader] = this._systemId
|
117
120
|
}
|
121
|
+
if (this._handle) {
|
122
|
+
headers[HandleHeader] = this._handle
|
123
|
+
}
|
118
124
|
return {
|
119
125
|
url,
|
120
126
|
method: method,
|
@@ -251,6 +257,7 @@ export class StormClient {
|
|
251
257
|
body: JSON.stringify(prompt.pages),
|
252
258
|
headers: {
|
253
259
|
'systemId': prompt.systemId,
|
260
|
+
'conversationId': prompt.systemId,
|
254
261
|
},
|
255
262
|
});
|
256
263
|
return (await response.json()) as HTMLPage[];
|
package/src/stormService.ts
CHANGED
@@ -149,14 +149,14 @@ export class StormService {
|
|
149
149
|
},
|
150
150
|
['.']
|
151
151
|
);
|
152
|
-
const stormClient = new StormClient(systemId);
|
152
|
+
const stormClient = new StormClient(handle, systemId);
|
153
153
|
await stormClient.uploadSystem(handle, systemId, await fs.readFile(tarballFile));
|
154
154
|
}
|
155
155
|
|
156
156
|
async installProjectById(handle: string, systemId: string) {
|
157
157
|
const tarballFile = this.getConversationTarball(systemId);
|
158
158
|
const destDir = path.dirname(tarballFile);
|
159
|
-
const stormClient = new StormClient(systemId);
|
159
|
+
const stormClient = new StormClient(handle, systemId);
|
160
160
|
const buffer = await stormClient.downloadSystem(handle, systemId);
|
161
161
|
await fs.mkdir(destDir, { recursive: true });
|
162
162
|
await fs.writeFile(tarballFile, buffer);
|