mirror of
https://github.com/kolbytn/mindcraft.git
synced 2025-04-22 06:02:07 +02:00
141 lines
No EOL
4.8 KiB
JavaScript
141 lines
No EOL
4.8 KiB
JavaScript
import { writeFile, readFile, unlink } from 'fs';
|
|
|
|
export class Coder {
|
|
constructor(agent) {
|
|
this.agent = agent;
|
|
this.current_code = '';
|
|
this.file_counter = 0;
|
|
this.fp = './agent_code/';
|
|
this.agent.bot.interrupt_code = false;
|
|
this.executing = false;
|
|
this.agent.bot.output = '';
|
|
this.code_template = '';
|
|
|
|
readFile(this.fp+'template.js', 'utf8', (err, data) => {
|
|
if (err) throw err;
|
|
console.log('Template str:', data);
|
|
this.code_template = data;
|
|
});
|
|
}
|
|
|
|
queueCode(code) {
|
|
this.current_code = this.santitizeCode(code);
|
|
}
|
|
|
|
santitizeCode(code) {
|
|
const remove_strs = ['javascript', 'js']
|
|
for (let r of remove_strs) {
|
|
if (code.startsWith(r)) {
|
|
code = code.slice(r.length);
|
|
return code;
|
|
}
|
|
}
|
|
// this may cause problems in callback functions
|
|
code = code.replaceAll(';\n', '; if(bot.interrupt_code) {log(bot, "Code interrupted.");return;}\n');
|
|
return code;
|
|
}
|
|
|
|
hasCode() {
|
|
return this.current_code.length > 0;
|
|
}
|
|
|
|
writeFilePromise(filename, src) {
|
|
// makes it so we can await this function
|
|
return new Promise((resolve, reject) => {
|
|
writeFile(filename, src, (err) => {
|
|
if (err) {
|
|
reject(err);
|
|
} else {
|
|
resolve();
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
|
|
// returns {success: bool, message: string, interrupted: bool}
|
|
async execute() {
|
|
if (!this.current_code) return {success: false, message: "No code to execute.", interrupted: false};
|
|
if (!this.code_template) return {success: false, message: "Code template not loaded.", interrupted: false};
|
|
let src = '';
|
|
for (let line of this.current_code.split('\n')) {
|
|
src += ` ${line}\n`;
|
|
}
|
|
src = this.code_template.replace('/* CODE HERE */', src);
|
|
|
|
console.log("writing to file...", src)
|
|
|
|
let filename = this.fp + this.file_counter + '.js';
|
|
// if (this.file_counter > 0) {
|
|
// let prev_filename = this.fp + (this.file_counter-1) + '.js';
|
|
// unlink(prev_filename, (err) => {
|
|
// console.log("deleted file " + prev_filename);
|
|
// if (err) console.error(err);
|
|
// });
|
|
// } commented for now, useful to keep files for debugging
|
|
this.file_counter++;
|
|
|
|
let write_result = await this.writeFilePromise(filename, src);
|
|
|
|
if (write_result) {
|
|
console.error('Error writing code execution file: ' + result);
|
|
return {success: false, message: result, interrupted: false};
|
|
}
|
|
|
|
try {
|
|
console.log('executing code...\n');
|
|
let execution_file = await import('.'+filename);
|
|
await this.stop();
|
|
|
|
this.executing = true;
|
|
await execution_file.main(this.agent.bot);
|
|
this.executing = false;
|
|
|
|
this.agent.bot.emit('finished_executing');
|
|
let output = this.formatOutput(this.agent.bot);
|
|
let interrupted = this.agent.bot.interrupt_code;
|
|
this.clear();
|
|
return {success:true, message: output, interrupted};
|
|
} catch (err) {
|
|
this.executing = false;
|
|
this.agent.bot.emit('finished_executing');
|
|
console.error("Code execution triggered catch:" + err);
|
|
let message = this.formatOutput(this.agent.bot);
|
|
message += '!!Code threw exception!! Error: ' + err;
|
|
let interrupted = this.agent.bot.interrupt_code;
|
|
await this.stop();
|
|
return {success: false, message, interrupted};
|
|
}
|
|
}
|
|
|
|
formatOutput(bot) {
|
|
if (bot.interrupt_code) return '';
|
|
let output = bot.output;
|
|
const MAX_OUT = 1000;
|
|
if (output.length > MAX_OUT) {
|
|
output = `Code output is very long (${output.length} chars) and has been shortened.\n
|
|
First outputs:\n${output.substring(0, MAX_OUT/2)}\n...skipping many lines.\nFinal outputs:\n ${output.substring(output.length - MAX_OUT/2)}`;
|
|
}
|
|
else {
|
|
output = 'Code output:\n' + output;
|
|
}
|
|
return output;
|
|
}
|
|
|
|
async stop() {
|
|
while (this.executing) {
|
|
this.agent.bot.interrupt_code = true;
|
|
this.agent.bot.collectBlock.cancelTask();
|
|
this.agent.bot.pathfinder.stop();
|
|
console.log('waiting for code to finish executing... interrupt:', this.agent.bot.interrupt_code);
|
|
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
}
|
|
this.clear();
|
|
}
|
|
|
|
clear() {
|
|
this.current_code = '';
|
|
this.agent.bot.output = '';
|
|
this.agent.bot.interrupt_code = false;
|
|
}
|
|
} |