Skip to content

Commit 6937c54

Browse files
committed
Add tag validation and fatal error repair handling for code chunks
1 parent acf348a commit 6937c54

2 files changed

Lines changed: 104 additions & 26 deletions

File tree

‎src/addons/addons/ai-integration/helpers/codeChunkHandler.js‎

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,40 @@ const xmlSerializer = new XMLSerializer();
66
const xmlParser = new DOMParser();
77
const blockParser = new GetSVG();
88

9+
const allowedTags = [
10+
"xml",
11+
"block",
12+
"value",
13+
"shadow",
14+
"mutation",
15+
"field",
16+
"next",
17+
"variableCreationRequest",
18+
"listCreationRequest",
19+
"comment",
20+
]
21+
22+
23+
function getUniqueTagNames(xmlString) {
24+
const parser = new DOMParser();
25+
const xmlDoc = parser.parseFromString(xmlString, "application/xml");
26+
27+
const tags = new Set();
28+
29+
function extractTags(node) {
30+
if (node.nodeType === 1) {
31+
tags.add(node.nodeName);
32+
for (let child of node.children) {
33+
extractTags(child);
34+
}
35+
}
36+
}
37+
38+
extractTags(xmlDoc.documentElement);
39+
40+
return Array.from(tags);
41+
}
42+
943
export async function handleRawCodeChunk(codeChunk, uniqueCommentID,mainWorkspace) {
1044
let response = {
1145
"variables": [],
@@ -47,6 +81,16 @@ export async function handleRawCodeChunk(codeChunk, uniqueCommentID,mainWorkspac
4781
console.log("[DEBUG] received well formed code chunk");
4882
}
4983
if (response.status == "failedToParse") { response.status = "error"; return response };
84+
//get all the tags in the xml code
85+
let tags = getUniqueTagNames(codeChunk);
86+
//check if the tags are allowed
87+
let unallowedTags = tags.filter(tag => !allowedTags.includes(tag));
88+
if (unallowedTags.length > 0) {
89+
console.log("[DEBUG] received illegal tags", unallowedTags);
90+
response.errorLog = "The following tags are not allowed: " + unallowedTags.join(", ") + ". Please attempt to fix the code.";
91+
response.status = "error_fixable";
92+
return response;
93+
}
5094
while (xmlCode.getElementsByTagName("variableCreationRequest").length > 0) {
5195
if (xmlCode.getElementsByTagName("variableCreationRequest")[0].getAttribute("type") == "broadcast_msg") {
5296
response.broadcasts.push(xmlCode.getElementsByTagName("variableCreationRequest")[0].textContent);

‎src/addons/addons/ai-integration/main.js‎

Lines changed: 60 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -461,22 +461,24 @@ export default class main {
461461
var randomId = Math.random().toString(36).substr(2, 5).toUpperCase();
462462
document.AI_INTEGRATION.CodeChunks = streamResult.match(/```(.*?)```/gs) || [];
463463
document.AI_INTEGRATION.processedCodeChunks = [];
464-
464+
465465
const processedChunks = await Promise.all(
466466
document.AI_INTEGRATION.CodeChunks.map((chunk, index) =>
467467
handleRawCodeChunk(chunk, `${randomId}_${index}`, main.mainWorkspace)
468468
)
469469
);
470-
470+
471471
document.AI_INTEGRATION.processedCodeChunks = processedChunks;
472-
472+
473473
let instanceCount = -1;
474474
var editedStreamResult = streamResult.replaceAll(/```(.*?)```/gs, "CODECHUNK23407283947");
475475
editedStreamResult = converter.makeHtml(editedStreamResult)
476476
editedStreamResult = editedStreamResult.replaceAll("CODECHUNK23407283947", () => {
477477
instanceCount++;
478478
if (document.AI_INTEGRATION.processedCodeChunks[instanceCount].status == "error") {
479479
return "<h1 class=\"errorMessage\">failed to parse Code Chunk</h1><br>"
480+
}else if (document.AI_INTEGRATION.processedCodeChunks[instanceCount].status == "error_fixable"){
481+
return "<div class=\"codeChunkOverlay\" id=\"errorFixable_" + randomId + "_" + instanceCount + "\"></div>";
480482
}
481483
document.AI_INTEGRATION.AllCodeChunksEverAdded.push(document.AI_INTEGRATION.processedCodeChunks[instanceCount]);
482484
let Div = document.createElement('div');
@@ -496,7 +498,7 @@ export default class main {
496498
codeBlockHeight.push(theDiv.children[xx].children[1].getBoundingClientRect().height);
497499
}
498500
document.getElementById(`TEMPCODEBLOCK${instanceCount}`).remove();
499-
501+
500502
let svg = domParser.parseFromString(document.AI_INTEGRATION.processedCodeChunks[instanceCount].blocksAsSVG, "text/html");
501503
svg = svg.body.children[0];
502504
for (var i = 0; i < svg.children.length; i++) {
@@ -505,30 +507,62 @@ export default class main {
505507
}
506508
return `<div class="codeChunkOverlay"><div class="insert_button_parent"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-6 insert_button" uniqueid="${document.AI_INTEGRATION.AllCodeChunksEverAdded.length}"><path stroke-linecap="round" stroke-linejoin="round" d="M3 16.5v2.25A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75V16.5M16.5 12 12 16.5m0 0L7.5 12m4.5 4.5V3"></path></svg></div><div class="codeChunkOverlay_child"><div id="CODEBLOCK_${randomId}_${instanceCount}">${svg.outerHTML}</div></div></div>`;
507509
});
508-
510+
509511
document.getElementById('currentlyBlabberingOnThis').innerHTML = editedStreamResult;
510512
for (let i = 0; i <= instanceCount; i++) { // each code block
511513
try {
512514
if (document.AI_INTEGRATION.processedCodeChunks[instanceCount].status == "error") {
513515
document.getElementById('currentlyBlabberingOnThis').id = '';
514516
console.warn("DEBUG: skipping codeblock #" + instanceCount + " due to status failure", document.AI_INTEGRATION.processedCodeChunks[instanceCount])
515517
return;
518+
}else if (document.AI_INTEGRATION.processedCodeChunks[instanceCount].status == "error_fixable") {
519+
var div = document.createElement('div');
520+
div.innerHTML = `<p style="text-align: center;">A fatal issue was detected with this code</p><div style="display: flex;margin: 10px;"></div>`;
521+
var button = document.createElement('button');
522+
button.innerHTML = "Attempt to Repair";
523+
button.style = "margin-left:auto;margin-right: auto;background-color: transparent;border: 1px solid var(--ui-tertiary);padding: 5px 10px;border-radius: 5px;";
524+
button.addEventListener('click', (e) => {
525+
button.innerHTML = "Attempting to Repair...";
526+
button.disabled = true;
527+
e.preventDefault();
528+
e.stopPropagation();
529+
//create new message
530+
var userMessage = document.createElement('div');
531+
userMessage.className = 'user-message';
532+
userMessage.innerHTML = `
533+
<div class="message">
534+
<span>Attempting to repair code block</span>
535+
<span>
536+
<div class="FileAttachment">
537+
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="svg">
538+
<path d="M2 7V14.7519H4.53246L5.9122 16.0909H8.12402L9.50376 14.7519H22V7H9.50376L8.12402 8.33905H5.9122L4.53246 7H2Z" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" stroke="currentcolor"></path>
539+
</svg>
540+
<p class="p">Error Logs</p>
541+
</div>
542+
</span>
543+
</div>
544+
`;
545+
document.getElementById('chat_content').appendChild(userMessage);
546+
requestChat(document.AI_INTEGRATION.processedCodeChunks[instanceCount].errorLog);
547+
});
548+
div.children[1].appendChild(button);
549+
document.getElementById(`errorFixable_${randomId}_${i}`).appendChild(div);
516550
}
517551
let currentWidth = 150;
518552
for (var xx = 0; xx < document.getElementById(`CODEBLOCK_${randomId}_${i}`).children[0].children.length; xx++) { //each top level block
519553
if (document.querySelector('.container').style.display != "") {
520554
document.querySelector('.container').style.display = '';
521555
document.querySelector('.container').style.zIndex = 509;
522556
}
523-
557+
524558
const currentElement = document.getElementById(`CODEBLOCK_${randomId}_${i}`).children[0].children[xx];
525559
currentElement.style.width = (currentElement.getBoundingClientRect().width * (currentWidth / currentElement.children[1].children[0].getBoundingClientRect().width)) + "px";
526-
560+
527561
//THE SMARTED/MOST INSANE CODE THAT WORKS IN THE HISTORY OF JS
528562
const currentText = currentElement.querySelector("text");
529563
const oldText = currentText.innerHTML;
530564
currentText.innerHTML = "a";
531-
565+
532566
var currentHeight = currentText.getBoundingClientRect().height;
533567
//console.log(currentText);
534568
while (currentHeight > 16 && currentWidth > 5) {
@@ -582,7 +616,7 @@ export default class main {
582616
}
583617
});
584618
}
585-
619+
586620
var totalWidth = 0;
587621
//Blockly.Xml.domToWorkspace(xml, workspace);
588622
Array.from(xml.children).forEach(block => {
@@ -603,7 +637,7 @@ export default class main {
603637
newBlock.moveBy(x, y);*/
604638
}
605639
var message = `<p style="font-weight: 900;margin-bottom: 10px;">Adding this code will:</p><ul>`;
606-
640+
607641
var [listNames, variableNames] = helpers.workspaceVariables(false, main.mainWorkspace);
608642
var newVariables = [];
609643
var newLists = [];
@@ -641,7 +675,7 @@ export default class main {
641675
var replacingBlocks = [];
642676
var replacingBlocksInternal = [];
643677
var trulyNewBlocks = [];
644-
678+
645679
for (var block of newBlocks) {
646680
var matchingBlock = currentWorkspaceBlocks.find(currentBlock => currentBlock.customBlockName === block.customBlockName);
647681
if (matchingBlock) {
@@ -655,7 +689,7 @@ export default class main {
655689
if (trulyNewBlocks.length > 0) {
656690
message += `<li>Create ${trulyNewBlocks.length} new block${trulyNewBlocks.length == 1 ? "" : "s"}: ${trulyNewBlocks.join(", ")}</li>`;
657691
}
658-
692+
659693
// List blocks that are being replaced
660694
if (replacingBlocks.length > 0) {
661695
message += `<li>Replace ${replacingBlocks.length} existing block${replacingBlocks.length == 1 ? "" : "s"}: ${replacingBlocks.join(", ")} <span><p class="errorMessage">(THIS WILL REPLACE YOUR CURRENT BLOCK DEFINITION)</p></span></li>`;
@@ -668,14 +702,14 @@ export default class main {
668702
const title = "Add Code to Workspace?";
669703
ScratchBlocks.prompt(message, null, callback, title, ScratchBlocks.BROADCAST_MESSAGE_VARIABLE_TYPE, true);
670704
});
671-
705+
672706
var errorForChunk = [];
673707
for (var xx = 0; xx < document.AI_INTEGRATION.errorsDetected.length; xx++) {
674708
if (document.AI_INTEGRATION.errorsDetected[xx].uniqueCommentID == currentElement.parentElement.id.replace("CODEBLOCK_", "")) {
675709
errorForChunk.push(document.AI_INTEGRATION.errorsDetected[xx]);
676710
}
677711
}
678-
712+
679713
if (errorForChunk.length == 0) {
680714
currentElement.parentElement.style = "width: fit-content;height: fit-content;margin: auto;";
681715
} else {
@@ -708,18 +742,18 @@ export default class main {
708742
var userMessage = document.createElement('div');
709743
userMessage.className = 'user-message';
710744
userMessage.innerHTML = `
711-
<div class="message">
712-
<span>Attempting to repair code block</span>
713-
<span>
714-
<div class="FileAttachment">
715-
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="svg">
716-
<path d="M2 7V14.7519H4.53246L5.9122 16.0909H8.12402L9.50376 14.7519H22V7H9.50376L8.12402 8.33905H5.9122L4.53246 7H2Z" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" stroke="currentcolor"></path>
717-
</svg>
718-
<p class="p">Error Logs</p>
719-
</div>
720-
</span>
721-
</div>
722-
`;
745+
<div class="message">
746+
<span>Attempting to repair code block</span>
747+
<span>
748+
<div class="FileAttachment">
749+
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="svg">
750+
<path d="M2 7V14.7519H4.53246L5.9122 16.0909H8.12402L9.50376 14.7519H22V7H9.50376L8.12402 8.33905H5.9122L4.53246 7H2Z" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" stroke="currentcolor"></path>
751+
</svg>
752+
<p class="p">Error Logs</p>
753+
</div>
754+
</span>
755+
</div>
756+
`;
723757
document.getElementById('chat_content').appendChild(userMessage);
724758
requestChat("the following errors occured while trying to parse the code (attempt to fix them):" + errorForChunk.map(error => error.error || "Unknown error").join("\n"));
725759
});

0 commit comments

Comments
 (0)