mirror of
https://github.com/kolbytn/mindcraft.git
synced 2025-08-09 08:45:33 +02:00
better conversation monitor timers, examples, bot detection
This commit is contained in:
parent
5649cec439
commit
c2dab95061
8 changed files with 106 additions and 39 deletions
|
@ -12,7 +12,7 @@
|
|||
"modes": {
|
||||
"self_preservation": true,
|
||||
"unstuck": true,
|
||||
"cowardice": true,
|
||||
"cowardice": false,
|
||||
"self_defense": true,
|
||||
"hunting": true,
|
||||
"item_collecting": true,
|
||||
|
@ -35,6 +35,13 @@
|
|||
{"role": "assistant", "content": "Hey John, not much. Just saying hi. Bye! !endConversation('john_goodman')"}
|
||||
],
|
||||
|
||||
[
|
||||
{"role": "system", "content": "work together with the other bot"},
|
||||
{"role": "assistant", "content": "!startConversation(\"terrance\", \"Hey gpt! Let's work together on this.\"))"},
|
||||
{"role": "user", "content": "terrance: (FROM OTHER BOT)Sounds good, what should we do first?"},
|
||||
{"role": "assistant", "content": "I'll start by collecting some resources. !collectBlocks('stone', 10)"}
|
||||
],
|
||||
|
||||
[
|
||||
{"role": "system", "content": "trade something with zorro_34"},
|
||||
{"role": "assistant", "content": "!startConversation(\"zorro_34\", \"Hey let's trade. What do you have?\")"},
|
||||
|
@ -126,6 +133,11 @@
|
|||
{"role": "assistant", "content": "I'll have to search a wider area. !searchForBlock(\"oak_log\", 100)"}
|
||||
],
|
||||
|
||||
[
|
||||
{"role": "system", "content": "Code output: Placed oak_planks at (-154, 96, -228)."},
|
||||
{"role": "assistant", "content": "I've placed an oak plank for the house. Wait, I should use newAction to build complicated structures! !newAction(\"Build a house with oak planks\")"}
|
||||
],
|
||||
|
||||
[
|
||||
{"role": "user", "content": "trixy88: craft some sticks"},
|
||||
{"role": "assistant", "content": "!craftRecipe(\"stick\", 4)"},
|
||||
|
|
|
@ -108,10 +108,16 @@ export class ActionManager {
|
|||
this.currentActionFn = null;
|
||||
clearTimeout(TIMEOUT);
|
||||
this.cancelResume();
|
||||
console.error("Code execution triggered catch: " + err);
|
||||
console.error("Code execution triggered catch:", err);
|
||||
// Log the full stack trace
|
||||
console.error(err.stack);
|
||||
await this.stop();
|
||||
|
||||
let message = this._getBotOutputSummary() + '!!Code threw exception!! Error: ' + err;
|
||||
let message = this._getBotOutputSummary() +
|
||||
'!!Code threw exception!!\n' +
|
||||
'Error: ' + err + '\n' +
|
||||
'Stack trace:\n' + err.stack;
|
||||
|
||||
let interrupted = this.agent.bot.interrupt_code;
|
||||
this.agent.clearBotLogs();
|
||||
if (!interrupted && !this.agent.coder.generating) {
|
||||
|
|
|
@ -224,7 +224,7 @@ export class Agent {
|
|||
}
|
||||
}
|
||||
|
||||
if (!self_prompt)
|
||||
if (from_other_bot)
|
||||
this.last_sender = source;
|
||||
|
||||
// Now translate the message
|
||||
|
@ -311,7 +311,7 @@ export class Agent {
|
|||
|
||||
async routeResponse(to_player, message) {
|
||||
let self_prompt = to_player === 'system' || to_player === this.name;
|
||||
if (self_prompt && this.last_sender && !this.self_prompter.on) {
|
||||
if (self_prompt && this.last_sender) {
|
||||
// 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;
|
||||
|
@ -320,7 +320,6 @@ export class Agent {
|
|||
if (convoManager.isOtherAgent(to_player) && convoManager.inConversation(to_player)) {
|
||||
// if we're in an ongoing conversation with the other bot, send the response to it
|
||||
convoManager.sendToBot(to_player, message);
|
||||
|
||||
}
|
||||
else {
|
||||
// otherwise, use open chat
|
||||
|
|
|
@ -116,7 +116,7 @@ export const actionsList = [
|
|||
description: 'Find and go to the nearest block of a given type in a given range.',
|
||||
params: {
|
||||
'type': { type: 'BlockName', description: 'The block type to go to.' },
|
||||
'search_range': { type: 'float', description: 'The range to search for the block.', domain: [0, 512] }
|
||||
'search_range': { type: 'float', description: 'The range to search for the block.', domain: [32, 512] }
|
||||
},
|
||||
perform: runAsAction(async (agent, block_type, range) => {
|
||||
await skills.goToNearestBlock(agent.bot, block_type, 4, range);
|
||||
|
@ -127,7 +127,7 @@ export const actionsList = [
|
|||
description: 'Find and go to the nearest entity of a given type in a given range.',
|
||||
params: {
|
||||
'type': { type: 'string', description: 'The type of entity to go to.' },
|
||||
'search_range': { type: 'float', description: 'The range to search for the entity.', domain: [0, 512] }
|
||||
'search_range': { type: 'float', description: 'The range to search for the entity.', domain: [32, 512] }
|
||||
},
|
||||
perform: runAsAction(async (agent, entity_type, range) => {
|
||||
await skills.goToNearestEntity(agent.bot, entity_type, 4, range);
|
||||
|
@ -386,10 +386,12 @@ export const actionsList = [
|
|||
'message': { type: 'string', description: 'The message to send.' },
|
||||
},
|
||||
perform: async function (agent, player_name, message) {
|
||||
if (convoManager.inConversation())
|
||||
return 'You are already in conversation';
|
||||
if (convoManager.inConversation() && !convoManager.inConversation(player_name))
|
||||
return 'You are already in conversation with other bot.';
|
||||
if (!convoManager.isOtherAgent(player_name))
|
||||
return player_name + ' is not a bot, cannot start conversation.';
|
||||
if (convoManager.inConversation(player_name))
|
||||
agent.history.add('system', 'You are already in conversation with ' + player_name + ' Don\'t use this command to talk to them.');
|
||||
convoManager.startConversation(player_name, message);
|
||||
}
|
||||
},
|
||||
|
|
|
@ -48,15 +48,11 @@ export const queryList = [
|
|||
|
||||
|
||||
let players = world.getNearbyPlayerNames(bot);
|
||||
let bots = [];
|
||||
for (const player of players) {
|
||||
if (convoManager.isOtherAgent(player))
|
||||
bots.push(player);
|
||||
}
|
||||
players = players.filter(p => !convoManager.isOtherAgent(p));
|
||||
let bots = convoManager.getInGameAgents().filter(b => b !== agent.name);
|
||||
players = players.filter(p => !bots.includes(p));
|
||||
|
||||
res += '\n- Nearby Human Players: ' + players.join(', ');
|
||||
res += '\n- Nearby Bot Players: ' + bots.join(', ');
|
||||
res += '\n- Nearby Human Players: ' + (players.length > 0 ? players.join(', ') : 'None.');
|
||||
res += '\n- Nearby Bot Players: ' + (bots.length > 0 ? bots.join(', ') : 'None.');
|
||||
|
||||
res += '\n' + agent.bot.modes.getMiniDocs() + '\n';
|
||||
return pad(res);
|
||||
|
@ -137,12 +133,8 @@ export const queryList = [
|
|||
let bot = agent.bot;
|
||||
let res = 'NEARBY_ENTITIES';
|
||||
let players = world.getNearbyPlayerNames(bot);
|
||||
let bots = [];
|
||||
for (const player of players) {
|
||||
if (convoManager.isOtherAgent(player))
|
||||
bots.push(player);
|
||||
}
|
||||
players = players.filter(p => !convoManager.isOtherAgent(p));
|
||||
let bots = convoManager.getInGameAgents().filter(b => b !== agent.name);
|
||||
players = players.filter(p => !bots.includes(p));
|
||||
|
||||
for (const player of players) {
|
||||
res += `\n- Human player: ${player}`;
|
||||
|
|
|
@ -44,11 +44,14 @@ class Conversation {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
const WAIT_TIME_START = 30000;
|
||||
class ConversationManager {
|
||||
constructor() {
|
||||
this.convos = {};
|
||||
this.activeConversation = null;
|
||||
this.awaiting_response = false;
|
||||
this.connection_timeout = null;
|
||||
this.wait_time_limit = WAIT_TIME_START;
|
||||
}
|
||||
|
||||
initAgent(a) {
|
||||
|
@ -63,23 +66,60 @@ class ConversationManager {
|
|||
|
||||
_startMonitor() {
|
||||
clearInterval(this.connection_monitor);
|
||||
let wait_time = 0;
|
||||
let last_time = Date.now();
|
||||
this.connection_monitor = setInterval(() => {
|
||||
if (!this.activeConversation) {
|
||||
clearInterval(this.connection_monitor);
|
||||
this._stopMonitor();
|
||||
return; // will clean itself up
|
||||
}
|
||||
let cur_name = this.activeConversation.name;
|
||||
if (!this.otherAgentInGame(cur_name)) {
|
||||
|
||||
let delta = Date.now() - last_time;
|
||||
last_time = Date.now();
|
||||
let convo_partner = this.activeConversation.name;
|
||||
|
||||
if (this.awaiting_response && agent.isIdle()) {
|
||||
wait_time += delta;
|
||||
if (wait_time > this.wait_time_limit) {
|
||||
agent.handleMessage('system', `${convo_partner} hasn't responded in ${this.wait_time_limit/1000} seconds, respond with a message to them or your own action.`);
|
||||
wait_time = 0;
|
||||
this.wait_time_limit*=2;
|
||||
}
|
||||
}
|
||||
else if (!this.awaiting_response){
|
||||
this.wait_time_limit = WAIT_TIME_START;
|
||||
wait_time = 0;
|
||||
}
|
||||
|
||||
if (!this.otherAgentInGame(convo_partner) && !this.connection_timeout) {
|
||||
this.connection_timeout = setTimeout(() => {
|
||||
if (this.otherAgentInGame(convo_partner)){
|
||||
this._clearMonitorTimeouts();
|
||||
return;
|
||||
}
|
||||
if (!self_prompter_paused) {
|
||||
this.endConversation(cur_name);
|
||||
agent.handleMessage('system', `${cur_name} disconnected, conversation has ended.`);
|
||||
this.endConversation(convo_partner);
|
||||
agent.handleMessage('system', `${convo_partner} disconnected, conversation has ended.`);
|
||||
}
|
||||
else {
|
||||
this.endConversation(cur_name);
|
||||
}
|
||||
this.endConversation(convo_partner);
|
||||
}
|
||||
}, 10000);
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
_stopMonitor() {
|
||||
clearInterval(this.connection_monitor);
|
||||
this.connection_monitor = null;
|
||||
this._clearMonitorTimeouts();
|
||||
}
|
||||
|
||||
_clearMonitorTimeouts() {
|
||||
this.awaiting_response = false;
|
||||
clearTimeout(this.connection_timeout);
|
||||
this.connection_timeout = null;
|
||||
}
|
||||
|
||||
async startConversation(send_to, message) {
|
||||
const convo = this._getConvo(send_to);
|
||||
|
@ -97,6 +137,13 @@ class ConversationManager {
|
|||
this.sendToBot(send_to, message, true);
|
||||
}
|
||||
|
||||
startConversationFromOtherBot(name) {
|
||||
const convo = this._getConvo(name);
|
||||
convo.active = true;
|
||||
this.activeConversation = convo;
|
||||
this._startMonitor();
|
||||
}
|
||||
|
||||
sendToBot(send_to, message, start=false) {
|
||||
if (!this.isOtherAgent(send_to)) {
|
||||
agent.bot.whisper(send_to, message);
|
||||
|
@ -118,6 +165,7 @@ class ConversationManager {
|
|||
end,
|
||||
};
|
||||
|
||||
this.awaiting_response = true;
|
||||
sendBotChatToServer(send_to, json);
|
||||
}
|
||||
|
||||
|
@ -132,10 +180,12 @@ class ConversationManager {
|
|||
|
||||
if (recieved.start) {
|
||||
convo.reset();
|
||||
this.startConversationFromOtherBot(sender);
|
||||
}
|
||||
if (convo.ignore_until_start)
|
||||
return;
|
||||
|
||||
this._clearMonitorTimeouts();
|
||||
convo.queue(recieved);
|
||||
|
||||
// responding to conversation takes priority over self prompting
|
||||
|
@ -167,6 +217,10 @@ class ConversationManager {
|
|||
agents_in_game = agents.filter(a => a.in_game).map(a => a.name);
|
||||
}
|
||||
|
||||
getInGameAgents() {
|
||||
return agents_in_game;
|
||||
}
|
||||
|
||||
inConversation(other_agent=null) {
|
||||
if (other_agent)
|
||||
return this.convos[other_agent]?.active;
|
||||
|
@ -176,6 +230,7 @@ class ConversationManager {
|
|||
endConversation(sender) {
|
||||
if (this.convos[sender]) {
|
||||
this.convos[sender].end();
|
||||
this._stopMonitor();
|
||||
this.activeConversation = null;
|
||||
if (self_prompter_paused && !this.inConversation()) {
|
||||
_resumeSelfPrompter();
|
||||
|
@ -276,7 +331,7 @@ function _handleFullInMessage(sender, recieved) {
|
|||
|
||||
let message = _tagMessage(recieved.message);
|
||||
if (recieved.end) {
|
||||
convo.end();
|
||||
convoManager.endConversation(sender);
|
||||
sender = 'system'; // bot will respond to system instead of the other bot
|
||||
message = `Conversation with ${sender} ended with message: "${message}"`;
|
||||
}
|
||||
|
|
|
@ -238,7 +238,7 @@ export function getNearbyPlayerNames(bot) {
|
|||
* @example
|
||||
* let players = world.getNearbyPlayerNames(bot);
|
||||
**/
|
||||
let players = getNearbyPlayers(bot, 16);
|
||||
let players = getNearbyPlayers(bot, 64);
|
||||
let found = [];
|
||||
for (let i = 0; i < players.length; i++) {
|
||||
if (!found.includes(players[i].username) && players[i].username != bot.username) {
|
||||
|
|
|
@ -2,6 +2,7 @@ import * as skills from './library/skills.js';
|
|||
import * as world from './library/world.js';
|
||||
import * as mc from '../utils/mcdata.js';
|
||||
import settings from '../../settings.js'
|
||||
import convoManager from './conversation.js';
|
||||
|
||||
async function say(agent, message) {
|
||||
agent.bot.modes.behavior_log += message + '\n';
|
||||
|
@ -294,7 +295,7 @@ async function execute(mode, agent, func, timeout=-1) {
|
|||
|
||||
if (should_reprompt) {
|
||||
// auto prompt to respond to the interruption
|
||||
let role = agent.last_sender ? agent.last_sender : 'system';
|
||||
let role = convoManager.inConversation() ? agent.last_sender : 'system';
|
||||
let logs = agent.bot.modes.flushBehaviorLog();
|
||||
agent.handleMessage(role, `(AUTO MESSAGE)Your previous action '${interrupted_action}' was interrupted by ${mode.name}.
|
||||
Your behavior log: ${logs}\nRespond accordingly.`);
|
||||
|
|
Loading…
Add table
Reference in a new issue