@kapeta/local-cluster-service 0.75.0 → 0.76.1
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/PageGenerator.d.ts +2 -1
- package/dist/cjs/src/storm/PageGenerator.js +6 -4
- 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 +16 -13
- 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 +6 -4
- 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 +16 -13
- 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 +6 -4
- package/src/storm/codegen.ts +2 -297
- package/src/storm/routes.ts +16 -13
- 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({
|
@@ -292,8 +293,9 @@ router.delete('/ui/serve/:systemId', async (req: KapetaBodyRequest, res: Respons
|
|
292
293
|
res.status(200).json({ status: 'ok' });
|
293
294
|
});
|
294
295
|
|
295
|
-
router.post('/ui/screen', async (req: KapetaBodyRequest, res: Response) => {
|
296
|
+
router.post('/:handle/ui/screen', async (req: KapetaBodyRequest, res: Response) => {
|
296
297
|
try {
|
298
|
+
const handle = req.params.handle as string;
|
297
299
|
const conversationId = req.headers[ConversationIdHeader.toLowerCase()] as string | undefined;
|
298
300
|
const systemId = req.headers[SystemIdHeader.toLowerCase()] as string | undefined;
|
299
301
|
|
@@ -306,7 +308,7 @@ router.post('/ui/screen', async (req: KapetaBodyRequest, res: Response) => {
|
|
306
308
|
|
307
309
|
const parentConversationId = systemId ?? '';
|
308
310
|
|
309
|
-
const queue = new PageQueue(parentConversationId, '', 5);
|
311
|
+
const queue = new PageQueue(handle, parentConversationId, '', 5);
|
310
312
|
onRequestAborted(req, res, () => {
|
311
313
|
queue.cancel();
|
312
314
|
});
|
@@ -348,7 +350,7 @@ router.post('/:handle/ui/iterative', async (req: KapetaBodyRequest, res: Respons
|
|
348
350
|
const conversationId = req.headers[ConversationIdHeader.toLowerCase()] as string | undefined;
|
349
351
|
|
350
352
|
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
|
353
|
+
const client = new StormClient(handle, conversationId); //todo is this correct we are using the landing page getConversationId down below as well
|
352
354
|
const landingPagesStream = await client.createUILandingPages(aiRequest, conversationId);
|
353
355
|
|
354
356
|
onRequestAborted(req, res, () => {
|
@@ -411,7 +413,7 @@ router.post('/:handle/ui/iterative', async (req: KapetaBodyRequest, res: Respons
|
|
411
413
|
systemPrompt.resolve(aiRequest.prompt);
|
412
414
|
});
|
413
415
|
|
414
|
-
const pageQueue = new PageQueue(systemId, await systemPrompt.promise, 5);
|
416
|
+
const pageQueue = new PageQueue(handle, systemId, await systemPrompt.promise, 5);
|
415
417
|
onRequestAborted(req, res, () => {
|
416
418
|
pageQueue.cancel();
|
417
419
|
});
|
@@ -457,7 +459,7 @@ router.post('/:handle/ui', async (req: KapetaBodyRequest, res: Response) => {
|
|
457
459
|
(req.headers[ConversationIdHeader.toLowerCase()] as string | undefined) || randomUUID();
|
458
460
|
|
459
461
|
const aiRequest: BasePromptRequest = JSON.parse(req.stringBody ?? '{}');
|
460
|
-
const stormClient = new StormClient(outerConversationId);
|
462
|
+
const stormClient = new StormClient(handle, outerConversationId);
|
461
463
|
// Get user journeys
|
462
464
|
const userJourneysStream = await stormClient.createUIUserJourneys(aiRequest, outerConversationId);
|
463
465
|
|
@@ -572,7 +574,7 @@ router.post('/:handle/ui', async (req: KapetaBodyRequest, res: Response) => {
|
|
572
574
|
shellsStream.abort();
|
573
575
|
});
|
574
576
|
|
575
|
-
const queue = new PageQueue(outerConversationId, systemPrompt, 5);
|
577
|
+
const queue = new PageQueue(handle, outerConversationId, systemPrompt, 5);
|
576
578
|
queue.setUiTheme(theme);
|
577
579
|
|
578
580
|
shellsStream.on('data', (data: StormEvent) => {
|
@@ -671,15 +673,16 @@ router.post('/:handle/ui', async (req: KapetaBodyRequest, res: Response) => {
|
|
671
673
|
}
|
672
674
|
});
|
673
675
|
|
674
|
-
router.post('/ui/edit', async (req: KapetaBodyRequest, res: Response) => {
|
676
|
+
router.post('/:handle/ui/edit', async (req: KapetaBodyRequest, res: Response) => {
|
675
677
|
try {
|
678
|
+
const handle = req.params.handle as string;
|
676
679
|
const systemId = (req.headers[SystemIdHeader.toLowerCase()] ||
|
677
680
|
req.headers[ConversationIdHeader.toLowerCase()]) as string | undefined;
|
678
681
|
|
679
682
|
const aiRequest: StormContextRequest<UIPageEditRequest> = JSON.parse(req.stringBody ?? '{}');
|
680
683
|
const storagePrefix = systemId ? systemId + '_' : 'mock_';
|
681
684
|
|
682
|
-
const queue = new PageQueue(systemId!, '', 5);
|
685
|
+
const queue = new PageQueue(handle, systemId!, '', 5);
|
683
686
|
|
684
687
|
onRequestAborted(req, res, () => {
|
685
688
|
queue.cancel();
|
@@ -753,7 +756,7 @@ router.post('/ui/vote', async (req: KapetaBodyRequest, res: Response) => {
|
|
753
756
|
const aiRequest: UIPageVoteRequest = JSON.parse(req.stringBody ?? '{}');
|
754
757
|
const { topic, vote, mainConversationId } = aiRequest;
|
755
758
|
try {
|
756
|
-
const stormClient = new StormClient(mainConversationId);
|
759
|
+
const stormClient = new StormClient("", mainConversationId);
|
757
760
|
await stormClient.voteUIPage(topic, conversationId, vote, mainConversationId);
|
758
761
|
} catch (e: any) {
|
759
762
|
res.status(500).send({ error: e.message });
|
@@ -765,7 +768,7 @@ router.post('/ui/get-vote', async (req: KapetaBodyRequest, res: Response) => {
|
|
765
768
|
const aiRequest: UIPageGetVoteRequest = JSON.parse(req.stringBody ?? '{}');
|
766
769
|
const { topic, mainConversationId } = aiRequest;
|
767
770
|
try {
|
768
|
-
const stormClient = new StormClient(mainConversationId);
|
771
|
+
const stormClient = new StormClient("", mainConversationId);
|
769
772
|
const vote = await stormClient.getVoteUIPage(topic, conversationId, mainConversationId);
|
770
773
|
res.send({ vote });
|
771
774
|
} catch (e: any) {
|
@@ -797,7 +800,7 @@ async function handleAll(req: KapetaBodyRequest, res: Response) {
|
|
797
800
|
const conversationId = req.headers[ConversationIdHeader.toLowerCase()] as string | undefined;
|
798
801
|
|
799
802
|
const aiRequest: BasePromptRequest = JSON.parse(req.stringBody ?? '{}');
|
800
|
-
const stormClient = new StormClient(systemId);
|
803
|
+
const stormClient = new StormClient(handle, systemId);
|
801
804
|
const metaStream = await stormClient.createMetadata(aiRequest, conversationId);
|
802
805
|
|
803
806
|
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);
|