mirror of
https://github.com/kolbytn/mindcraft.git
synced 2025-08-12 10:15:33 +02:00
148 lines
5.2 KiB
JavaScript
148 lines
5.2 KiB
JavaScript
![]() |
export class TaskManager {
|
||
|
constructor(agent) {
|
||
|
this.agent = agent;
|
||
|
this.executing = false;
|
||
|
this.currentTaskLabel = '';
|
||
|
this.currentTaskFn = null;
|
||
|
this.timedout = false;
|
||
|
this.resume_func = null;
|
||
|
this.resume_name = '';
|
||
|
}
|
||
|
|
||
|
async resumeTask(taskFn, timeout) {
|
||
|
return this._executeResume(taskFn, timeout);
|
||
|
}
|
||
|
|
||
|
async runTask(taskLabel, taskFn, { timeout, resume = false } = {}) {
|
||
|
if (resume) {
|
||
|
return this._executeResume(taskFn, timeout);
|
||
|
} else {
|
||
|
return this._executeTask(taskLabel, taskFn, timeout);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
async stop() {
|
||
|
if (!this.executing) return;
|
||
|
console.trace();
|
||
|
const start = Date.now();
|
||
|
while (this.executing) {
|
||
|
this.agent.interruptBot();
|
||
|
console.log('waiting for code to finish executing...');
|
||
|
await new Promise(resolve => setTimeout(resolve, 1000));
|
||
|
if (Date.now() - start > 10 * 1000) {
|
||
|
this.agent.cleanKill('Code execution refused stop after 10 seconds. Killing process.');
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
cancelResume() {
|
||
|
this.resume_func = null;
|
||
|
this.resume_name = null;
|
||
|
}
|
||
|
|
||
|
async _executeResume(taskFn = null, timeout = 10) {
|
||
|
const new_resume = taskFn != null;
|
||
|
if (new_resume) { // start new resume
|
||
|
this.resume_func = taskFn;
|
||
|
this.resume_name = this.currentTaskLabel;
|
||
|
}
|
||
|
if (this.resume_func != null && this.agent.isIdle() && (!this.agent.self_prompter.on || new_resume)) {
|
||
|
this.currentTaskLabel = this.resume_name;
|
||
|
let res = await this._executeTask(this.resume_name, this.resume_func, timeout);
|
||
|
this.currentTaskLabel = '';
|
||
|
return res;
|
||
|
} else {
|
||
|
return { success: false, message: null, interrupted: false, timedout: false };
|
||
|
}
|
||
|
}
|
||
|
|
||
|
async _executeTask(taskLabel, taskFn, timeout = 10) {
|
||
|
let TIMEOUT;
|
||
|
try {
|
||
|
console.log('executing code...\n');
|
||
|
|
||
|
// await current task to finish (executing=false), with 10 seconds timeout
|
||
|
// also tell agent.bot to stop various actions
|
||
|
if (this.executing) {
|
||
|
console.log(`new task "${taskLabel}" trying to interrupt current task "${this.currentTaskLabel}"`);
|
||
|
}
|
||
|
await this.stop();
|
||
|
|
||
|
// clear bot logs and reset interrupt code
|
||
|
this.agent.clearBotLogs();
|
||
|
|
||
|
this.executing = true;
|
||
|
this.currentTaskLabel = taskLabel;
|
||
|
this.currentTaskFn = taskFn;
|
||
|
|
||
|
// timeout in minutes
|
||
|
if (timeout > 0) {
|
||
|
TIMEOUT = this._startTimeout(timeout);
|
||
|
}
|
||
|
|
||
|
// start the task
|
||
|
await taskFn();
|
||
|
|
||
|
// mark task as finished + cleanup
|
||
|
this.executing = false;
|
||
|
this.currentTaskLabel = '';
|
||
|
this.currentTaskFn = null;
|
||
|
clearTimeout(TIMEOUT);
|
||
|
|
||
|
// get bot activity summary
|
||
|
let output = this._getBotOutputSummary();
|
||
|
let interrupted = this.agent.bot.interrupt_code;
|
||
|
let timedout = this.timedout;
|
||
|
this.agent.clearBotLogs();
|
||
|
|
||
|
// if not interrupted and not generating, emit idle event
|
||
|
if (!interrupted && !this.agent.coder.generating) {
|
||
|
this.agent.bot.emit('idle');
|
||
|
}
|
||
|
|
||
|
// return task status report
|
||
|
return { success: true, message: output, interrupted, timedout };
|
||
|
} catch (err) {
|
||
|
this.executing = false;
|
||
|
this.currentTaskLabel = '';
|
||
|
this.currentTaskFn = null;
|
||
|
clearTimeout(TIMEOUT);
|
||
|
this.cancelResume();
|
||
|
console.error("Code execution triggered catch: " + err);
|
||
|
await this.stop();
|
||
|
|
||
|
let message = this._getBotOutputSummary() + '!!Code threw exception!! Error: ' + err;
|
||
|
let interrupted = this.agent.bot.interrupt_code;
|
||
|
this.agent.clearBotLogs();
|
||
|
if (!interrupted && !this.agent.coder.generating) {
|
||
|
this.agent.bot.emit('idle');
|
||
|
}
|
||
|
return { success: false, message, interrupted, timedout: false };
|
||
|
}
|
||
|
}
|
||
|
|
||
|
_getBotOutputSummary() {
|
||
|
const { bot } = this.agent;
|
||
|
if (bot.interrupt_code && !this.timedout) return '';
|
||
|
let output = bot.output;
|
||
|
const MAX_OUT = 500;
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
_startTimeout(TIMEOUT_MINS = 10) {
|
||
|
return setTimeout(async () => {
|
||
|
console.warn(`Code execution timed out after ${TIMEOUT_MINS} minutes. Attempting force stop.`);
|
||
|
this.timedout = true;
|
||
|
this.agent.history.add('system', `Code execution timed out after ${TIMEOUT_MINS} minutes. Attempting force stop.`);
|
||
|
await this.stop(); // last attempt to stop
|
||
|
}, TIMEOUT_MINS * 60 * 1000);
|
||
|
}
|
||
|
|
||
|
}
|