From 61e1010e490158911509dc65500c6bf01e16e508 Mon Sep 17 00:00:00 2001 From: MaxRobinsonTheGreat Date: Fri, 15 Aug 2025 16:14:27 -0500 Subject: [PATCH] a few protections from infinite loops --- src/agent/action_manager.js | 21 +++++++++++++++++++++ src/agent/agent.js | 6 +++++- src/agent/library/skills.js | 4 +++- 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/agent/action_manager.js b/src/agent/action_manager.js index 3af3c2b..470f507 100644 --- a/src/agent/action_manager.js +++ b/src/agent/action_manager.js @@ -7,6 +7,8 @@ export class ActionManager { this.timedout = false; this.resume_func = null; this.resume_name = ''; + this.last_action_time = 0; + this.recent_action_counter = 0; } async resumeAction(actionFn, timeout) { @@ -59,6 +61,25 @@ export class ActionManager { async _executeAction(actionLabel, actionFn, timeout = 10) { let TIMEOUT; try { + if (this.last_action_time > 0) { + let time_diff = Date.now() - this.last_action_time; + if (time_diff < 20) { + this.recent_action_counter++; + } + else { + this.recent_action_counter = 0; + } + if (this.recent_action_counter > 2) { + console.warn('Fast action loop detected, cancelling resume.'); + this.cancelResume(); // likely cause of repetition + } + if (this.recent_action_counter > 5) { + console.error('Infinite action loop detected, shutting down.'); + this.agent.cleanKill('Infinite action loop detected, shutting down.'); + return { success: false, message: 'Infinite action loop detected, shutting down.', interrupted: false, timedout: false }; + } + } + this.last_action_time = Date.now(); console.log('executing code...\n'); // await current action to finish (executing=false), with 10 seconds timeout diff --git a/src/agent/agent.js b/src/agent/agent.js index f478764..4a7a4a1 100644 --- a/src/agent/agent.js +++ b/src/agent/agent.js @@ -439,7 +439,11 @@ export class Agent { this.bot.clearControlStates(); this.bot.pathfinder.stop(); // clear any lingering pathfinder this.bot.modes.unPauseAll(); - this.actions.resumeAction(); + setTimeout(() => { + if (this.isIdle()) { + this.actions.resumeAction(); + } + }, 1000); }); // Init NPC controller diff --git a/src/agent/library/skills.js b/src/agent/library/skills.js index 8fd5086..68cd4d0 100644 --- a/src/agent/library/skills.js +++ b/src/agent/library/skills.js @@ -1084,13 +1084,15 @@ function startDoorInterval(bot) { // shuffle positions so we're not always opening the same door const positions = [ bot.entity.position.clone(), - bot.entity.position.offset(0, 0, 1), // north + bot.entity.position.offset(0, 0, 1), bot.entity.position.offset(0, 0, -1), bot.entity.position.offset(1, 0, 0), bot.entity.position.offset(-1, 0, 0), ] let elevated_positions = positions.map(position => position.offset(0, 1, 0)); positions.push(...elevated_positions); + positions.push(bot.entity.position.offset(0, 2, 0)); // above head + positions.push(bot.entity.position.offset(0, -1, 0)); // below feet let currentIndex = positions.length; while (currentIndex != 0) {