mirror of
https://github.com/kolbytn/mindcraft.git
synced 2025-07-23 16:35:19 +02:00
additional task features
This commit is contained in:
parent
4e0611d29e
commit
a15ab15bcd
6 changed files with 68 additions and 96 deletions
|
@ -11,7 +11,6 @@
|
|||
"andy",
|
||||
"randy"
|
||||
],
|
||||
"agent_number": 2,
|
||||
"initial_inventory": {
|
||||
"andy": {
|
||||
"iron_ingot": 1
|
||||
|
@ -26,13 +25,8 @@
|
|||
"type": "construction",
|
||||
"goal": "Build a house"
|
||||
},
|
||||
"multiagent_techtree_1_shears_with_2_iron_ingot": {
|
||||
"goal": "Collaborate with other agents to build a shear.",
|
||||
"agent_names": [
|
||||
"andy",
|
||||
"randy"
|
||||
],
|
||||
"agent_number": 2,
|
||||
"techtree_1_shears_with_2_iron_ingot": {
|
||||
"goal": "Build a shear.",
|
||||
"initial_inventory": {
|
||||
"andy": {
|
||||
"iron_ingot": 1
|
||||
|
@ -48,11 +42,11 @@
|
|||
},
|
||||
"multiagent_techtree_1_stone_pickaxe": {
|
||||
"goal": "Collaborate with other agents to build an stone pickaxe",
|
||||
"conversation": "Let's build a stone pickaxe",
|
||||
"agent_names": [
|
||||
"andy",
|
||||
"randy"
|
||||
],
|
||||
"agent_number": 2,
|
||||
"initial_inventory": {
|
||||
"andy": {
|
||||
"wooden_pickaxe": 1
|
||||
|
@ -65,45 +59,5 @@
|
|||
"number_of_target": 1,
|
||||
"type": "techtree",
|
||||
"timeout": 300
|
||||
},
|
||||
"multiagent_build_wooden_pickaxe": {
|
||||
"goal": "Collaborate with other agents to build a wooden pickaxe.",
|
||||
"agent_names": [
|
||||
"andy",
|
||||
"randy"
|
||||
],
|
||||
"agent_number": 2,
|
||||
"initial_inventory": {
|
||||
"andy": {
|
||||
"oak_log": 2
|
||||
},
|
||||
"randy": {
|
||||
"stick": 2
|
||||
}
|
||||
},
|
||||
"target": "wooden_pickaxe",
|
||||
"number_of_target": 1,
|
||||
"type": "techtree",
|
||||
"timeout": 120
|
||||
},
|
||||
"multiagent_techtree_boat": {
|
||||
"goal": "Collaborate with other agents to build a birch boat.",
|
||||
"agent_names": [
|
||||
"Bob",
|
||||
"Alice"
|
||||
],
|
||||
"agent_number": 2,
|
||||
"initial_inventory": {
|
||||
"Bob": {
|
||||
"birch_planks": 3
|
||||
},
|
||||
"Alice": {
|
||||
"birch_planks": 2
|
||||
}
|
||||
},
|
||||
"target": "birch_boat",
|
||||
"number_of_target": 1,
|
||||
"type": "techtree",
|
||||
"timeout": 60
|
||||
}
|
||||
}
|
|
@ -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, responseScheduledFor} from './conversation.js';
|
||||
import { isOtherAgent, initConversationManager, sendToBot, endAllChats, responseScheduledFor, inConversation } from './conversation.js';
|
||||
import { handleTranslation, handleEnglishTranslation } from '../utils/translator.js';
|
||||
import { addViewer } from './viewer.js';
|
||||
import settings from '../../settings.js';
|
||||
|
@ -18,6 +18,7 @@ import { loadTask, initBotTask, TechTreeHarvestValidator } from '../utils/tasks.
|
|||
export class Agent {
|
||||
async start(profile_fp, load_mem=false, init_message=null, count_id=0, task_path=null, task_id=null) {
|
||||
this.last_sender = null;
|
||||
this.count_id = count_id;
|
||||
try {
|
||||
if (!profile_fp) {
|
||||
throw new Error('No profile filepath provided');
|
||||
|
@ -66,10 +67,16 @@ export class Agent {
|
|||
this.taskTimeout = this.task.timeout || 300;
|
||||
this.taskStartTime = Date.now();
|
||||
this.validator = new TechTreeHarvestValidator(this.task, this.bot);
|
||||
this.blocked_actions = this.task.blocked_actions || [];
|
||||
if (this.task.goal)
|
||||
this.blocked_actions.push('!endGoal');
|
||||
if (this.task.conversation)
|
||||
this.blocked_actions.push('!endConversation');
|
||||
} else {
|
||||
this.task = null;
|
||||
this.taskTimeout = null;
|
||||
this.validator = null;
|
||||
this.blocked_actions = [];
|
||||
}
|
||||
console.log("Is validated:", this.validator && this.validator.validate());
|
||||
|
||||
|
@ -96,18 +103,13 @@ export class Agent {
|
|||
|
||||
console.log(`${this.name} spawned.`);
|
||||
this.clearBotLogs();
|
||||
|
||||
if (this.task) {
|
||||
await initBotTask(this.bot, this.task);
|
||||
await new Promise((resolve) => setTimeout(resolve, 10000));
|
||||
if (this.task.agent_names && this.task.agent_names.filter(name => !this.bot.players[name]).length) {
|
||||
console.log(`Missing players/bots: ${missingPlayers.join(', ')}`);
|
||||
this.cleanKill('Not all required players/bots are present in the world. Exiting.', 4);
|
||||
}
|
||||
}
|
||||
|
||||
this._setupEventHandlers(save_data, init_message);
|
||||
this.startEvents();
|
||||
|
||||
if (this.task)
|
||||
await initBotTask(this);
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error in spawn event:', error);
|
||||
process.exit(0);
|
||||
|
@ -437,18 +439,24 @@ export class Agent {
|
|||
}, INTERVAL);
|
||||
|
||||
// Check for task completion
|
||||
setInterval(async () => {
|
||||
if (this.task && this.validator && this.validator.validate())
|
||||
this.killBots();
|
||||
if (this.task && this.taskTimeout) {
|
||||
const elapsedTime = (Date.now() - this.taskStartTime) / 1000;
|
||||
if (elapsedTime >= this.taskTimeout) {
|
||||
console.log('Task timeout reached. Task unsuccessful.');
|
||||
this.cleanKill('Task unsuccessful: Timeout reached', 3);
|
||||
if (this.task) {
|
||||
setInterval(async () => {
|
||||
if (this.validator && this.validator.validate())
|
||||
this.killBots();
|
||||
if (this.task.goal && !this.self_prompter.on)
|
||||
this.cleanKill('Task unsuccessful: Agent ended goal', 3);
|
||||
if (this.task.conversation && !inConversation())
|
||||
this.cleanKill('Task unsuccessful: Agent ended conversation', 3);
|
||||
if (this.taskTimeout) {
|
||||
const elapsedTime = (Date.now() - this.taskStartTime) / 1000;
|
||||
if (elapsedTime >= this.taskTimeout) {
|
||||
console.log('Task timeout reached. Task unsuccessful.');
|
||||
this.cleanKill('Task unsuccessful: Timeout reached', 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}, 1000);
|
||||
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
this.bot.emit('idle');
|
||||
}
|
||||
|
|
|
@ -220,7 +220,7 @@ export async function executeCommand(agent, message) {
|
|||
}
|
||||
}
|
||||
|
||||
export function getCommandDocs() {
|
||||
export function getCommandDocs(blacklist=null) {
|
||||
const typeTranslations = {
|
||||
//This was added to keep the prompt the same as before type checks were implemented.
|
||||
//If the language model is giving invalid inputs changing this might help.
|
||||
|
@ -234,6 +234,9 @@ export function getCommandDocs() {
|
|||
Use the commands with the syntax: !commandName or !commandName("arg1", 1.2, ...) if the command takes arguments.\n
|
||||
Do not use codeblocks. Use double quotes for strings. Only use one command in each response, trailing commands and comments will be ignored.\n`;
|
||||
for (let command of commandList) {
|
||||
if (blacklist && blacklist.includes(command.name)) {
|
||||
continue;
|
||||
}
|
||||
docs += command.name + ': ' + command.description + '\n';
|
||||
if (command.params) {
|
||||
docs += 'Params:\n';
|
||||
|
|
|
@ -173,7 +173,7 @@ export class Prompter {
|
|||
prompt = prompt.replaceAll('$ACTION', this.agent.actions.currentActionLabel);
|
||||
}
|
||||
if (prompt.includes('$COMMAND_DOCS'))
|
||||
prompt = prompt.replaceAll('$COMMAND_DOCS', getCommandDocs());
|
||||
prompt = prompt.replaceAll('$COMMAND_DOCS', getCommandDocs(this.agent.blocked_actions));
|
||||
if (prompt.includes('$CODE_DOCS'))
|
||||
prompt = prompt.replaceAll('$CODE_DOCS', getSkillDocs());
|
||||
if (prompt.includes('$EXAMPLES') && examples !== null)
|
||||
|
|
|
@ -26,19 +26,9 @@ export class AgentProcess {
|
|||
agentProcess.on('exit', (code, signal) => {
|
||||
console.log(`Agent process exited with code ${code} and signal ${signal}`);
|
||||
|
||||
if (code === 2) {
|
||||
console.log(`Task completed successfully`);
|
||||
process.exit(2, signal);
|
||||
}
|
||||
|
||||
if (code === 3) {
|
||||
console.log(`Task failed due to reaching timeout`);
|
||||
process.exit(3);
|
||||
}
|
||||
|
||||
if (code === 4) {
|
||||
console.log(`Task failed as all agents weren't correctly spawned `);
|
||||
process.exit(4);
|
||||
if (code > 1) {
|
||||
console.log(`Ending task`);
|
||||
process.exit(code);
|
||||
}
|
||||
|
||||
if (code !== 0) {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import yaml from 'js-yaml'
|
||||
import { readFileSync } from 'fs';
|
||||
import {getPosition} from './library/world.js'
|
||||
import { executeCommand } from './commands/index.js';
|
||||
import { getPosition } from './library/world.js'
|
||||
|
||||
export function loadTask(taskId) {
|
||||
try {
|
||||
|
@ -19,17 +20,18 @@ export function loadTask(taskId) {
|
|||
}
|
||||
}
|
||||
|
||||
export async function initBotTask(bot, task, name) {
|
||||
if (task) {
|
||||
bot.chat(`/clear ${bot.username}`);
|
||||
console.log(`Cleared ${bot.username}'s inventory.`);
|
||||
}
|
||||
export async function initBotTask(agent) {
|
||||
let bot = agent.bot;
|
||||
let task = agent.task;
|
||||
|
||||
bot.chat(`/clear ${bot.username}`);
|
||||
console.log(`Cleared ${bot.username}'s inventory.`);
|
||||
|
||||
//wait for a bit so inventory is cleared
|
||||
await new Promise((resolve) => setTimeout(resolve, 500));
|
||||
|
||||
console.log(task && "agent_number" in task && task.agent_number > 1);
|
||||
if (task && "agent_number" in task && task.agent_number > 1) {
|
||||
console.log("agent_number" in task.agent_number > 1);
|
||||
if ("agent_number" in task.agent_number > 1) {
|
||||
var initial_inventory = task.initial_inventory[bot.username];
|
||||
console.log("Initial inventory:", initial_inventory);
|
||||
} else if (task) {
|
||||
|
@ -37,7 +39,7 @@ export async function initBotTask(bot, task, name) {
|
|||
var initial_inventory = task.initial_inventory;
|
||||
}
|
||||
|
||||
if (task && "initial_inventory" in task) {
|
||||
if ("initial_inventory" in task) {
|
||||
console.log("Setting inventory...");
|
||||
console.log("Inventory to set:", initial_inventory);
|
||||
for (let key of Object.keys(initial_inventory)) {
|
||||
|
@ -70,7 +72,7 @@ export async function initBotTask(bot, task, name) {
|
|||
|
||||
// teleport near a human player if found by default
|
||||
|
||||
if (task && "agent_number" in task) {
|
||||
if ("agent_number" in task) {
|
||||
var agent_names = task.agent_names;
|
||||
if (human_player_name) {
|
||||
console.log(`Teleporting ${bot.username} to human ${human_player_name}`)
|
||||
|
@ -103,7 +105,7 @@ export async function initBotTask(bot, task, name) {
|
|||
This was done by MaxRobinson in one of the youtube videos.
|
||||
*/
|
||||
|
||||
if (task && task.type !== 'construction') {
|
||||
if (task.type !== 'construction') {
|
||||
const pos = getPosition(bot);
|
||||
const xOffset = getRandomOffset(5);
|
||||
const zOffset = getRandomOffset(5);
|
||||
|
@ -111,7 +113,22 @@ export async function initBotTask(bot, task, name) {
|
|||
await new Promise((resolve) => setTimeout(resolve, 200));
|
||||
}
|
||||
|
||||
if (task.goal) {
|
||||
await executeCommand(agent, `!goal("${task.goal}")`);
|
||||
}
|
||||
|
||||
if (task.agent_names) {
|
||||
await new Promise((resolve) => setTimeout(resolve, 10000));
|
||||
if (task.agent_names.filter(name => !bot.players[name]).length) {
|
||||
console.log(`Missing players/bots: ${missingPlayers.join(', ')}`);
|
||||
agent.cleanKill('Not all required players/bots are present in the world. Exiting.', 4);
|
||||
}
|
||||
}
|
||||
|
||||
if (task.conversation && agent.count_id === 0) {
|
||||
let other_name = task.agent_names.filter(name => name !== bot.username)[0];
|
||||
await executeCommand(agent, `!startConversation("${other_name}", "${task.conversation}")`);
|
||||
}
|
||||
}
|
||||
|
||||
export class TechTreeHarvestValidator {
|
||||
|
|
Loading…
Add table
Reference in a new issue