Skip to content

Commit 9ed83da

Browse files
authored
Merge pull request #3 from Titanium2099/toolbox_context
Toolbox context
2 parents 3cd038a + db459a8 commit 9ed83da

4 files changed

Lines changed: 111 additions & 10 deletions

File tree

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ const manifest = {
66
"description": "Adds AI integration into the editor including code completion, code generation, sprite generation, background generation, and more.\n\n\nDISCLAIMER: We do not store any request data or your API keys. Your API keys are only sent with requests and remain fully stored locally on your computer. All models we use are free, ensuring no charges apply. However, for added security, we recommend setting restrictions on your API keys. If you'd like to verify this, our AI backend is open-source—feel free to check it out yourself!",
77
"info": [
88
{
9-
"text": "If you need help with creating an API key, check out our guide here: https://blog.codetorch.net/gemini-api-key-for-torchy/",
9+
"text": "If you need help with creating an API key, check out our guides here: https://blog.codetorch.net/gemini-api-key-for-torchy/ , https://blog.codetorch.net/openrouter-api-key-for-torchy/",
1010
"id": "warning"
1111
}
1212
],
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
{
2+
"overrides":{
3+
"control_forever":"<block type=\"control_forever\"><statement name=\"SUBSTACK\"></statement></block>",
4+
"control_if":"<block type=\"control_if\"><value name=\"CONDITION\"></value><statement name=\"SUBSTACK\"></statement></block>",
5+
"control_if_else":"<block type=\"control_if_else\"><value name=\"CONDITION\"></value><statement name=\"SUBSTACK\"></statement></block>",
6+
"control_wait_until":"<block type=\"control_wait_until\"><value name=\"CONDITION\"></value></block>",
7+
"control_repeat_until":"<block type=\"control_repeat_until\"><value name=\"CONDITION\"></value><statement name=\"SUBSTACK\"></statement></block>",
8+
"control_while":"<block type=\"control_while\"><value name=\"CONDITION\"></value><statement name=\"SUBSTACK\"></statement></block>",
9+
"operator_and":"<block type=\"operator_and\"><value name=\"OPERAND1\"></value><value name=\"OPERAND2\"></value></block>",
10+
"operator_or":"<block type=\"operator_or\"><value name=\"OPERAND1\"></value><value name=\"OPERAND2\"></value></block>",
11+
"operator_not":"<block type=\"operator_not\"><value name=\"OPERAND\"></value></block>",
12+
"event_whenbroadcastreceived":"<block type=\"event_whenbroadcastreceived\"><field name=\"BROADCAST_OPTION\" variabletype=\"broadcast_msg\">message1</field></block>"
13+
},
14+
"insert":{
15+
"data_variable":"<block blockType=\"Stack\" type=\"data_variable\"><field name=\"VARIABLE\" variabletype=\"\">my variable</field></block>",
16+
"data_setvariableto":"<block blockType=\"Stack\" type=\"data_setvariableto\"><field name=\"VARIABLE\" variabletype=\"\">my variable</field><value name=\"VALUE\"><shadow type=\"text\"><field name=\"TEXT\">0</field></shadow></value></block>",
17+
"data_changevariableby":"<block blockType=\"Stack\" type=\"data_changevariableby\"><field name=\"VARIABLE\" variabletype=\"\">my variable</field><value name=\"VALUE\"><shadow type=\"math_number\"><field name=\"NUM\">1</field></shadow></value></block>",
18+
"data_showvariable":"<block blockType=\"Stack\" type=\"data_showvariable\"><field name=\"VARIABLE\" variabletype=\"\">my variable</field></block>",
19+
"data_hidevariable":"<block blockType=\"Stack\" type=\"data_hidevariable\"><field name=\"VARIABLE\" variabletype=\"\">my variable</field></block>",
20+
"data_listcontents":"<block blockType=\"Reporter\" type=\"data_listcontents\"><field name=\"LIST\" variabletype=\"list\">my list</field></block>",
21+
"data_addtolist":"<block blockType=\"Stack\" type=\"data_addtolist\"><field name=\"LIST\" variabletype=\"list\">my list</field><value name=\"ITEM\"><shadow type=\"text\"><field name=\"TEXT\">thing</field></shadow></value></block>",
22+
"data_deleteoflist":"<block blockType=\"Stack\" type=\"data_deleteoflist\"><field name=\"LIST\" variabletype=\"list\">my list</field><value name=\"INDEX\"><shadow type=\"math_integer\"><field name=\"NUM\">1</field></shadow></value></block>",
23+
"data_deletealloflist":"<block blockType=\"Stack\" type=\"data_deletealloflist\"><field name=\"LIST\" variabletype=\"list\">my list</field></block>",
24+
"data_insertatlist":"<block blockType=\"Stack\" type=\"data_insertatlist\"><field name=\"LIST\" variabletype=\"list\">my list</field><value name=\"ITEM\"><shadow type=\"text\"><field name=\"TEXT\">thing</field></shadow></value><value name=\"INDEX\"><shadow type=\"math_integer\"><field name=\"NUM\">1</field></shadow></value></block>",
25+
"data_replaceitemoflist":"<block blockType=\"Stack\" type=\"data_replaceitemoflist\"><field name=\"LIST\" variabletype=\"list\">my list</field><value name=\"INDEX\"><shadow type=\"math_integer\"><field name=\"NUM\">1</field></shadow></value><value name=\"ITEM\"><shadow type=\"text\"><field name=\"TEXT\">thing</field></shadow></value></block>",
26+
"data_itemoflist":"<block blockType=\"Reporter\" type=\"data_itemoflist\"><field name=\"LIST\" variabletype=\"list\">my list</field><value name=\"INDEX\"><shadow type=\"math_integer\"><field name=\"NUM\">1</field></shadow></value></block>",
27+
"data_itemnumoflist":"<block blockType=\"Reporter\" type=\"data_itemnumoflist\"><field name=\"LIST\" variabletype=\"list\">my list</field><value name=\"ITEM\"><shadow type=\"text\"><field name=\"TEXT\">thing</field></shadow></value></block>",
28+
"data_showlist":"<block blockType=\"Stack\" type=\"data_showlist\"><field name=\"LIST\" variabletype=\"list\">my list</field></block>",
29+
"data_lengthoflist":"<block blockType=\"Reporter\" type=\"data_lengthoflist\"><field name=\"LIST\" variabletype=\"list\">my list</field></block>",
30+
"data_listcontainsitem":"<block blockType=\"Boolean\" type=\"data_listcontainsitem\"><field name=\"LIST\" variabletype=\"list\">my list</field><value name=\"ITEM\"><shadow type=\"text\"><field name=\"TEXT\">thing</field></shadow></value></block>",
31+
"data_hidelist":"<block blockType=\"Stack\" type=\"data_hidelist\"><field name=\"LIST\" variabletype=\"list\">my list</field></block>"
32+
}
33+
}

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

Lines changed: 76 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
const toolboxOverrides = require('./assets/toolboxOverrides.json');
2+
13
export default class helpers {
24
constructor() {
35
}
@@ -99,6 +101,11 @@ export default class helpers {
99101
document.AI_INTEGRATION.chatHistory.push({ "role": "user", "message": messageContents });
100102
//document.AI_INTEGRATION.chatHistory.push({ "role": "assistant", "message": "Error reading response" }); //not sure if the AI needs to know that it failed
101103

104+
//clean up attachments
105+
document.AI_INTEGRATION.currentInputHasAttachment = false;
106+
if(document.getElementById('attachedFile') != null) document.getElementById('attachedFile').remove();
107+
108+
102109
document.AI_INTEGRATION.AI_currently_blabbering = false;
103110
if (document.getElementById('currentlyBlabberingOnThis') != null) {
104111
document.getElementById('currentlyBlabberingOnThis').innerHTML = "<h1 class=\"errorMessage\">Error reading response</h1>";
@@ -137,19 +144,19 @@ export default class helpers {
137144
const rootElement = xmlDoc.createElement("project");
138145
xmlDoc.appendChild(rootElement);
139146

140-
for(var x of addon.tab.redux.state.scratchGui.vm.runtime.targets){
141-
// Create a child element with text content
142-
const childElement = xmlDoc.createElement("sprite");
143-
childElement.innerHTML = x.blocks.toXML();
144-
rootElement.appendChild(childElement);
147+
for (var x of addon.tab.redux.state.scratchGui.vm.runtime.targets) {
148+
// Create a child element with text content
149+
const childElement = xmlDoc.createElement("sprite");
150+
childElement.innerHTML = x.blocks.toXML();
151+
rootElement.appendChild(childElement);
145152
}
146153
// Serialize XML to string
147154
const serializer = new XMLSerializer();
148155
const xmlString = serializer.serializeToString(xmlDoc);
149156

150157
console.log(xmlString);
151158
}
152-
static APIKeyRequiredModal(){
159+
static APIKeyRequiredModal() {
153160
const div = document.createElement('div');
154161
div.className = 'container';
155162
div.id = 'torchyPopup';
@@ -181,8 +188,69 @@ export default class helpers {
181188
</div>`;
182189
document.body.appendChild(div);
183190
document.getElementById('closePopup').addEventListener('click', () => {
184-
document.getElementById('torchyPopup').remove();
185-
document.AI_INTEGRATION.popupOpen = false;
191+
document.getElementById('torchyPopup').remove();
192+
document.AI_INTEGRATION.popupOpen = false;
186193
});
187194
}
195+
static returnSterilizedToolbox(Gaddon) {
196+
if (Gaddon == null) return;
197+
function extractBlockReturnType(block) {
198+
if (block) {
199+
var returnType = "Stack";
200+
if (block.outputConnection) {
201+
// Check if the block is a boolean
202+
if (block.outputConnection.check_ && block.outputConnection.check_.includes("Boolean")) {
203+
returnType = "Reporter";
204+
} else {
205+
returnType = "Boolean";
206+
}
207+
}
208+
return returnType;
209+
} else {
210+
return null;
211+
}
212+
}
213+
var workspace = new Blockly.Workspace();
214+
215+
var toolbox = Gaddon.tab.redux.state.scratchGui.toolbox.toolboxXML;
216+
var parser = new DOMParser();
217+
var xmlDoc = parser.parseFromString(toolbox, "text/xml");
218+
var sterializedToolbox = document.implementation.createDocument("", "", null);
219+
var rootElement = sterializedToolbox.createElement("toolbox");
220+
sterializedToolbox.appendChild(rootElement);
221+
var blocks = xmlDoc.getElementsByTagName("block");
222+
for (var block of blocks) {
223+
var blockElement = block.cloneNode(true);
224+
var newBlock = Blockly.Xml.domToBlock(blockElement, workspace)
225+
var returnType = extractBlockReturnType(newBlock);
226+
var blockCopy = block.cloneNode(true);
227+
228+
if (toolboxOverrides.overrides[blockCopy.getAttribute("type")] !== undefined) {
229+
var parser = new DOMParser();
230+
var xmlDoc = parser.parseFromString(toolboxOverrides.overrides[blockCopy.getAttribute("type")], "text/xml");
231+
var overrideBlockElement = xmlDoc.getElementsByTagName("block")[0];
232+
overrideBlockElement.setAttribute("blockType", returnType);
233+
rootElement.appendChild(overrideBlockElement);
234+
}else{
235+
blockCopy.removeAttribute("id");
236+
blockCopy.setAttribute("blockType", returnType);
237+
rootElement.appendChild(blockCopy);
238+
}
239+
}
240+
for(var x of Object.keys(toolboxOverrides.insert)){
241+
if (toolboxOverrides.insert[x] !== undefined) {
242+
var parser = new DOMParser();
243+
var xmlDoc = parser.parseFromString(toolboxOverrides.insert[x], "text/xml");
244+
var overrideBlockElement = xmlDoc.getElementsByTagName("block")[0];
245+
rootElement.appendChild(overrideBlockElement);
246+
}else{
247+
console.error("A REALlY WEIRD ERROR OCCURED");
248+
}
249+
}
250+
workspace.dispose();
251+
var serializer = new XMLSerializer();
252+
var xmlString = serializer.serializeToString(sterializedToolbox);
253+
console.log("[DEBUG] toolbox has # of blocks: " + sterializedToolbox.getElementsByTagName("block").length);
254+
return xmlString.replace(/>\s+</g, '><').trim();
255+
}
188256
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,7 @@ function popupFunctionality() {
376376
var data = {
377377
api_key: authTokenToUse,
378378
message: messageContents,
379-
history: document.AI_INTEGRATION.chatHistory,
379+
history: [{ "role": "user", "message": helpers.returnSterilizedToolbox(Gaddon,mainWorkspace) },...document.AI_INTEGRATION.chatHistory],
380380
ai_model: document.getElementById('AI_Selector_select').value,
381381
};
382382

0 commit comments

Comments
 (0)