improved interrupt response logic, removed collectallblocks

This commit is contained in:
MaxRobinsonTheGreat 2024-11-22 14:53:25 -06:00
parent 1fe1bda789
commit a853995571
5 changed files with 44 additions and 28 deletions

View file

@ -50,7 +50,7 @@
[
{"role": "user", "content": "gort: (FROM OTHER BOT)Let's do it, onward!"},
{"role": "assistant", "content": "Alright, let's see what's nearby... !nearbyBlocks"}
{"role": "assistant", "content": "Alright, I'll start by getting some cobblestone. !collectBlocks('stone', 10)"}
],
[

View file

@ -8,7 +8,7 @@ import { ActionManager } from './action_manager.js';
import { NPCContoller } from './npc/controller.js';
import { MemoryBank } from './memory_bank.js';
import { SelfPrompter } from './self_prompter.js';
import { isOtherAgent, initConversationManager, sendToBot, endAllChats } from './conversation.js';
import { isOtherAgent, initConversationManager, sendToBot, endAllChats, responseScheduledFor} from './conversation.js';
import { handleTranslation, handleEnglishTranslation } from '../utils/translator.js';
import { addViewer } from './viewer.js';
import settings from '../../settings.js';
@ -191,7 +191,7 @@ export class Agent {
}
else if (save_data?.last_sender) {
this.last_sender = save_data.last_sender;
await this.handleMessage(this.last_sender, `(You have restarted and this message is auto-generated. Continue the conversation with ${this.last_sender})`);
await this.handleMessage('system', `You have restarted and this message is auto-generated. Continue the conversation with ${this.last_sender}`);
}
else if (init_message) {
await this.handleMessage('system', init_message, 2);
@ -265,14 +265,12 @@ export class Agent {
if (!self_prompt)
this.last_sender = source;
else
this.last_sender = null;
// Now translate the message
message = await handleEnglishTranslation(message);
console.log('received message from', source, ':', message);
const checkInterrupt = () => this.self_prompter.shouldInterrupt(self_prompt) || this.shut_up;
const checkInterrupt = () => this.self_prompter.shouldInterrupt(self_prompt) || this.shut_up || responseScheduledFor(source);
let behavior_log = this.bot.modes.flushBehaviorLog();
if (behavior_log.trim().length > 0) {
@ -347,6 +345,13 @@ export class Agent {
}
async routeResponse(to_player, message, translate_up_to=-1) {
let self_prompt = to_player === 'system' || to_player === this.name;
if (self_prompt && this.last_sender && !this.self_prompter.on) {
// this is for when the agent is prompted by system while still in conversation
// so it can respond to events like death but be routed back to the last sender
to_player = this.last_sender;
}
if (isOtherAgent(to_player)) {
sendToBot(to_player, message);
return;
@ -362,7 +367,7 @@ export class Agent {
// newlines are interpreted as separate chats, which triggers spam filters. replace them with spaces
message = message.replaceAll('\n', ' ');
if (to_player === 'system' || to_player === this.name)
if (self_prompt)
this.bot.chat(message);
else
this.bot.whisper(to_player, message);

View file

@ -225,18 +225,6 @@ export const actionsList = [
await skills.collectBlock(agent.bot, type, num);
}, false, 10) // 10 minute timeout
},
{
name: '!collectAllBlocks',
description: 'Collect all the nearest blocks of a given type until told to stop.',
params: {
'type': { type: 'BlockName', description: 'The block type to collect.' }
},
perform: runAsAction(async (agent, type) => {
let success = await skills.collectBlock(agent.bot, type, 1);
if (!success)
agent.actions.cancelResume();
}, true, 3) // 3 minute timeout
},
{
name: '!craftRecipe',
description: 'Craft the given recipe a given number of times.',

View file

@ -106,7 +106,8 @@ export function sendToBot(send_to, message, start=false) {
const convo = _getConvo(send_to);
if (convo.ignore_until_start)
return;
convo.active = true;
const end = message.includes('!endConversation');
const json = {
'message': message,
@ -139,6 +140,14 @@ export async function recieveFromBot(sender, json) {
_scheduleProcessInMessage(sender, recieved, convo);
}
// returns true if the other bot has a scheduled response
export function responseScheduledFor(sender) {
if (!isOtherAgent(sender))
return false;
const convo = _getConvo(sender);
return !!convo.inMessageTimer;
}
/*
This function controls conversation flow by deciding when the bot responds.
@ -149,7 +158,7 @@ The logic is as follows:
- If both bots are busy, don't respond until someone is done, excluding a few actions that allow fast responses
- New messages recieved during the delay will reset the delay following this logic, and be queued to respond in bulk
*/
const talkOverActions = ['stay', 'followPlayer'];
const talkOverActions = ['stay', 'followPlayer', 'mode:']; // all mode actions
const fastDelay = 200;
const longDelay = 5000;
async function _scheduleProcessInMessage(sender, recieved, convo) {
@ -171,10 +180,16 @@ async function _scheduleProcessInMessage(sender, recieved, convo) {
scheduleResponse(longDelay);
else if (!agent.isIdle()) {
// I'm busy but other bot isn't
let shouldRespond = await agent.prompter.promptShouldRespondToBot(recieved.message);
console.log(`${agent.name} decided to ${shouldRespond?'respond':'not respond'} to ${sender}`);
if (shouldRespond)
let canTalkOver = talkOverActions.some(a => agent.actions.currentActionLabel.includes(a));
if (canTalkOver) {
scheduleResponse(fastDelay);
}
else {
let shouldRespond = await agent.prompter.promptShouldRespondToBot(recieved.message);
console.log(`${agent.name} decided to ${shouldRespond?'respond':'not respond'} to ${sender}`);
if (shouldRespond)
scheduleResponse(fastDelay);
}
}
else {
// neither are busy
@ -182,8 +197,7 @@ async function _scheduleProcessInMessage(sender, recieved, convo) {
}
}
export function _processInMessageQueue(name) {
function _processInMessageQueue(name) {
const convo = _getConvo(name);
let pack = null;
let full_message = '';
@ -195,10 +209,11 @@ export function _processInMessageQueue(name) {
_handleFullInMessage(name, pack);
}
export function _handleFullInMessage(sender, recieved) {
function _handleFullInMessage(sender, recieved) {
console.log(`responding to **${JSON.stringify(recieved)}**`);
const convo = _getConvo(sender);
convo.active = true;
const message = _tagMessage(recieved.message);
if (recieved.end) {
@ -209,6 +224,7 @@ export function _handleFullInMessage(sender, recieved) {
}
if (recieved.start)
agent.shut_up = false;
convo.inMessageTimer = null;
agent.handleMessage(sender, message);
}

View file

@ -288,7 +288,14 @@ async function execute(mode, agent, func, timeout=-1) {
}, { timeout });
mode.active = false;
console.log(`Mode ${mode.name} finished executing, code_return: ${code_return.message}`);
if (interrupted_action && !agent.actions.resume_func && !agent.self_prompter.on) {
let should_reprompt =
interrupted_action && // it interrupted a previous action
!agent.actions.resume_func && // there is no resume function
!agent.self_prompter.on && // self prompting is not on
!code_return.interrupted; // this mode action was not interrupted by something else
if (should_reprompt) {
// auto prompt to respond to the interruption
let role = agent.last_sender ? agent.last_sender : 'system';
let logs = agent.bot.modes.flushBehaviorLog();