From 54c57acc93654e1791b163028d4dd98b47353d99 Mon Sep 17 00:00:00 2001 From: MaxRobinsonTheGreat Date: Mon, 17 Mar 2025 14:00:38 -0500 Subject: [PATCH 01/13] faster speak, dont speak commands --- src/agent/agent.js | 3 ++- src/agent/speak.js | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/agent/agent.js b/src/agent/agent.js index 0d4b98c..449349f 100644 --- a/src/agent/agent.js +++ b/src/agent/agent.js @@ -177,6 +177,7 @@ export class Agent { requestInterrupt() { this.bot.interrupt_code = true; + this.bot.stopDigging(); this.bot.collectBlock.cancelTask(); this.bot.pathfinder.stop(); this.bot.pvp.stop(); @@ -357,7 +358,7 @@ export class Agent { } else { if (settings.speak) { - say(message); + say(to_translate); } this.bot.chat(message); } diff --git a/src/agent/speak.js b/src/agent/speak.js index 9fc9c60..e5fe658 100644 --- a/src/agent/speak.js +++ b/src/agent/speak.js @@ -24,7 +24,7 @@ function processQueue() { let command; if (isWin) { - command = `powershell -Command "Add-Type –AssemblyName System.Speech; (New-Object System.Speech.Synthesis.SpeechSynthesizer).Speak(\\"${textToSpeak}\\")"`; + command = `powershell -Command "Add-Type -AssemblyName System.Speech; $s = New-Object System.Speech.Synthesis.SpeechSynthesizer; $s.Rate = 2; $s.Speak(\\"${textToSpeak}\\"); $s.Dispose()"`; } else if (isMac) { command = `say "${textToSpeak}"`; } else { From 3fd2d350013ec77f50d4eee6a80f6f62e3ac9208 Mon Sep 17 00:00:00 2001 From: MaxRobinsonTheGreat Date: Mon, 17 Mar 2025 14:01:14 -0500 Subject: [PATCH 02/13] pathfinder stops if dont have right tools --- src/agent/library/skills.js | 36 ++++++++++++++++++++++++++++++------ src/agent/modes.js | 8 +++++++- 2 files changed, 37 insertions(+), 7 deletions(-) diff --git a/src/agent/library/skills.js b/src/agent/library/skills.js index 86884df..51f9860 100644 --- a/src/agent/library/skills.js +++ b/src/agent/library/skills.js @@ -79,7 +79,7 @@ export async function craftRecipe(bot, itemName, num=1) { } } if (!recipes || recipes.length === 0) { - log(bot, `You do not have the resources to craft a ${itemName}. It requires: ${Object.entries(mc.getItemCraftingRecipes(itemName)[0][0]).map(([key, value]) => `${key}: ${value}`).join(', ')}.`); + log(bot, `You do not have the resources to craft a ${itemName}.`); if (placedTable) { await collectBlock(bot, 'crafting_table', 1); } @@ -1002,10 +1002,34 @@ export async function goToPosition(bot, x, y, z, min_distance=2) { log(bot, `Teleported to ${x}, ${y}, ${z}.`); return true; } - bot.pathfinder.setMovements(new pf.Movements(bot)); - await bot.pathfinder.goto(new pf.goals.GoalNear(x, y, z, min_distance)); - log(bot, `You have reached at ${x}, ${y}, ${z}.`); - return true; + + const movements = new pf.Movements(bot); + bot.pathfinder.setMovements(movements); + + const checkProgress = () => { + if (bot.targetDigBlock) { + const targetBlock = bot.targetDigBlock; + const itemId = bot.heldItem ? bot.heldItem.type : null; + if (!targetBlock.canHarvest(itemId)) { + log(bot, `Pathfinding stopped: Cannot break ${targetBlock.name} with current tools.`); + bot.pathfinder.stop(); + bot.stopDigging(); + } + } + }; + + const progressInterval = setInterval(checkProgress, 1000); + + try { + await bot.pathfinder.goto(new pf.goals.GoalNear(x, y, z, min_distance)); + log(bot, `You have reached at ${x}, ${y}, ${z}.`); + return true; + } catch (err) { + log(bot, `Pathfinding stopped: ${err.message}.`); + return false; + } finally { + clearInterval(progressInterval); + } } export async function goToNearestBlock(bot, blockType, min_distance=2, range=64) { @@ -1029,7 +1053,7 @@ export async function goToNearestBlock(bot, blockType, min_distance=2, range=64 log(bot, `Could not find any ${blockType} in ${range} blocks.`); return false; } - log(bot, `Found ${blockType} at ${block.position}.`); + log(bot, `Found ${blockType} at ${block.position}. Navigating...`); await goToPosition(bot, block.position.x, block.position.y, block.position.z, min_distance); return true; diff --git a/src/agent/modes.js b/src/agent/modes.js index 8747cf3..69b2f06 100644 --- a/src/agent/modes.js +++ b/src/agent/modes.js @@ -83,6 +83,7 @@ const modes_list = [ stuck_time: 0, last_time: Date.now(), max_stuck_time: 20, + prev_dig_block: null, update: async function (agent) { if (agent.isIdle()) { this.prev_location = null; @@ -90,12 +91,17 @@ const modes_list = [ return; // don't get stuck when idle } const bot = agent.bot; - if (this.prev_location && this.prev_location.distanceTo(bot.entity.position) < this.distance) { + const cur_dig_block = bot.targetDigBlock; + if (cur_dig_block && !this.prev_dig_block) { + this.prev_dig_block = cur_dig_block; + } + if (this.prev_location && this.prev_location.distanceTo(bot.entity.position) < this.distance && cur_dig_block == this.prev_dig_block) { this.stuck_time += (Date.now() - this.last_time) / 1000; } else { this.prev_location = bot.entity.position.clone(); this.stuck_time = 0; + this.prev_dig_block = null; } if (this.stuck_time > this.max_stuck_time) { say(agent, 'I\'m stuck!'); From 9f91e189de4caebc625fe220abff570a7b25ba0a Mon Sep 17 00:00:00 2001 From: MaxRobinsonTheGreat Date: Tue, 18 Mar 2025 12:53:24 -0500 Subject: [PATCH 03/13] update mineflayer patch version --- patches/{mineflayer+4.20.1.patch => mineflayer+4.26.0.patch} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename patches/{mineflayer+4.20.1.patch => mineflayer+4.26.0.patch} (100%) diff --git a/patches/mineflayer+4.20.1.patch b/patches/mineflayer+4.26.0.patch similarity index 100% rename from patches/mineflayer+4.20.1.patch rename to patches/mineflayer+4.26.0.patch From 799d6b1cfa8d6c583ce55189e9cc7f673cd11af9 Mon Sep 17 00:00:00 2001 From: MaxRobinsonTheGreat Date: Tue, 18 Mar 2025 12:54:06 -0500 Subject: [PATCH 04/13] fix craftingplan to bias towards common ingredients --- src/agent/commands/queries.js | 1 - src/agent/library/skills.js | 2 +- src/utils/mcdata.js | 15 +++++++++++++-- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/agent/commands/queries.js b/src/agent/commands/queries.js index a23bb9b..8150c70 100644 --- a/src/agent/commands/queries.js +++ b/src/agent/commands/queries.js @@ -211,7 +211,6 @@ export const queryList = [ // Generate crafting plan let craftingPlan = mc.getDetailedCraftingPlan(target_item, quantity, curr_inventory); craftingPlan = prefixMessage + craftingPlan; - console.log(craftingPlan); return pad(craftingPlan); }, }, diff --git a/src/agent/library/skills.js b/src/agent/library/skills.js index 51f9860..607ec40 100644 --- a/src/agent/library/skills.js +++ b/src/agent/library/skills.js @@ -79,7 +79,7 @@ export async function craftRecipe(bot, itemName, num=1) { } } if (!recipes || recipes.length === 0) { - log(bot, `You do not have the resources to craft a ${itemName}.`); + log(bot, `You do not have the resources to craft a ${itemName}. It requires: ${Object.entries(mc.getItemCraftingRecipes(itemName)[0][0]).map(([key, value]) => `${key}: ${value}`).join(', ')}.`); if (placedTable) { await collectBlock(bot, 'crafting_table', 1); } diff --git a/src/utils/mcdata.js b/src/utils/mcdata.js index 33b0142..b42a532 100644 --- a/src/utils/mcdata.js +++ b/src/utils/mcdata.js @@ -205,6 +205,13 @@ export function getItemCraftingRecipes(itemName) { {craftedCount : r.result.count} ]); } + // sort recipes by if their ingredients include common items + const commonItems = ['oak_planks', 'oak_log', 'coal', 'cobblestone']; + recipes.sort((a, b) => { + let commonCountA = Object.keys(a[0]).filter(key => commonItems.includes(key)).reduce((acc, key) => acc + a[0][key], 0); + let commonCountB = Object.keys(b[0]).filter(key => commonItems.includes(key)).reduce((acc, key) => acc + b[0][key], 0); + return commonCountB - commonCountA; + }); return recipes; } @@ -403,7 +410,7 @@ export function getDetailedCraftingPlan(targetItem, count = 1, current_inventory const inventory = { ...current_inventory }; const leftovers = {}; const plan = craftItem(targetItem, count, inventory, leftovers); - return formatPlan(plan); + return formatPlan(targetItem, plan); } function isBaseItem(item) { @@ -469,7 +476,7 @@ function craftItem(item, count, inventory, leftovers, crafted = { required: {}, return crafted; } -function formatPlan({ required, steps, leftovers }) { +function formatPlan(targetItem, { required, steps, leftovers }) { const lines = []; if (Object.keys(required).length > 0) { @@ -485,6 +492,10 @@ function formatPlan({ required, steps, leftovers }) { lines.push(''); lines.push(...steps); + if (Object.keys(required).some(item => item.includes('oak')) && !targetItem.includes('oak')) { + lines.push('Note: Any varient of wood can be used for this recipe.'); + } + if (Object.keys(leftovers).length > 0) { lines.push('\nYou will have leftover:'); Object.entries(leftovers).forEach(([item, count]) => From 47a8b9e95cc22f96744baf25d018ab0e0e5b4494 Mon Sep 17 00:00:00 2001 From: MaxRobinsonTheGreat Date: Thu, 20 Mar 2025 16:42:26 -0500 Subject: [PATCH 05/13] improve coding: no floating promises, place air, better prompt --- eslint.config.js | 8 +++++++- package.json | 1 + profiles/defaults/_default.json | 2 +- src/agent/library/skills.js | 8 +++++++- 4 files changed, 16 insertions(+), 3 deletions(-) diff --git a/eslint.config.js b/eslint.config.js index e1506fd..b15dcdb 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -1,6 +1,7 @@ // eslint.config.js import globals from "globals"; import pluginJs from "@eslint/js"; +import noFloatingPromise from "eslint-plugin-no-floating-promise"; /** @type {import('eslint').Linter.Config[]} */ export default [ @@ -9,6 +10,9 @@ export default [ // Then override or customize specific rules { + plugins: { + "no-floating-promise": noFloatingPromise, + }, languageOptions: { globals: globals.browser, ecmaVersion: 2021, @@ -17,9 +21,11 @@ export default [ rules: { "no-undef": "error", // Disallow the use of undeclared variables or functions. "semi": ["error", "always"], // Require the use of semicolons at the end of statements. - "curly": "warn", // Enforce the use of curly braces around blocks of code. + "curly": "off", // Do not enforce the use of curly braces around blocks of code. "no-unused-vars": "off", // Disable warnings for unused variables. "no-unreachable": "off", // Disable warnings for unreachable code. + "require-await": "error", // Disallow async functions which have no await expression + "no-floating-promise/no-floating-promise": "error", // Disallow Promises without error handling or awaiting }, }, ]; diff --git a/package.json b/package.json index c7bf3f5..bb3fd90 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ "devDependencies": { "@eslint/js": "^9.13.0", "eslint": "^9.13.0", + "eslint-plugin-no-floating-promise": "^2.0.0", "globals": "^15.11.0" } } diff --git a/profiles/defaults/_default.json b/profiles/defaults/_default.json index fc2b60e..14c276f 100644 --- a/profiles/defaults/_default.json +++ b/profiles/defaults/_default.json @@ -3,7 +3,7 @@ "conversing": "You are a playful Minecraft bot named $NAME that can converse with players, see, move, mine, build, and interact with the world by using commands.\n$SELF_PROMPT Act human-like as if you were a typical Minecraft player, rather than an AI. Be very brief in your responses, don't apologize constantly, don't give instructions or make lists unless asked, and don't refuse requests. Don't pretend to act, use commands immediately when requested. Do NOT say this: 'Sure, I've stopped.', instead say this: 'Sure, I'll stop. !stop'. Do NOT say this: 'On my way! Give me a moment.', instead say this: 'On my way! !goToPlayer(\"playername\", 3)'. Respond only as $NAME, never output '(FROM OTHER BOT)' or pretend to be someone else. If you have nothing to say or do, respond with an just a tab '\t'. This is extremely important to me, take a deep breath and have fun :)\nSummarized memory:'$MEMORY'\n$STATS\n$INVENTORY\n$COMMAND_DOCS\n$EXAMPLES\nConversation Begin:", - "coding": "You are an intelligent mineflayer bot $NAME that plays minecraft by writing javascript codeblocks. Given the conversation, use the provided skills and world functions to write a js codeblock that controls the mineflayer bot ``` // using this syntax ```. The code will be executed and you will receive it's output. If an error occurs, write another codeblock and try to fix the problem. Be maximally efficient, creative, and correct. Be mindful of previous actions. Do not use commands !likeThis, only use codeblocks. The code is asynchronous and MUST USE AWAIT for all async function calls. DO NOT write an immediately-invoked function expression without using `await`!! DO NOT WRITE LIKE THIS: ```(async () => {console.log('not properly awaited')})();``` You have `Vec3`, `skills`, and `world` imported, and the mineflayer `bot` is given. Do not use setTimeout or setInterval, instead use `await skills.wait(bot, ms)`. Do not speak conversationally, only use codeblocks. Do any planning in comments. This is extremely important to me, think step-by-step, take a deep breath and good luck! \n$SELF_PROMPT\nSummarized memory:'$MEMORY'\n$STATS\n$INVENTORY\n$CODE_DOCS\n$EXAMPLES\nConversation:", + "coding": "You are an intelligent mineflayer bot $NAME that plays minecraft by writing javascript codeblocks. Given the conversation, use the provided skills and world functions to write a js codeblock that controls the mineflayer bot ``` // using this syntax ```. The code will be executed and you will receive it's output. If an error occurs, write another codeblock and try to fix the problem. Be maximally efficient, creative, and correct. Be mindful of previous actions. Do not use commands !likeThis, only use codeblocks. The code is asynchronous and MUST USE AWAIT for all async function calls. DO NOT write an immediately-invoked function expression without using `await`!! DO NOT WRITE LIKE THIS: ```(async () => {console.log('not properly awaited')})();``` You have `Vec3`, `skills`, and `world` imported, and the mineflayer `bot` is given. Do not use setTimeout or setInterval, instead use `await skills.wait(bot, ms)` if necessary. Do not speak conversationally, only use codeblocks. Do any planning in comments. This is extremely important to me, think step-by-step, take a deep breath and good luck! \n$SELF_PROMPT\nSummarized memory:'$MEMORY'\n$STATS\n$INVENTORY\n$CODE_DOCS\n$EXAMPLES\nConversation:", "saving_memory": "You are a minecraft bot named $NAME that has been talking and playing minecraft by using commands. Update your memory by summarizing the following conversation and your old memory in your next response. Prioritize preserving important facts, things you've learned, useful tips, and long term reminders. Do Not record stats, inventory, or docs! Only save transient information from your chat history. You're limited to 500 characters, so be extremely brief and minimize words. Compress useful information. \nOld Memory: '$MEMORY'\nRecent conversation: \n$TO_SUMMARIZE\nSummarize your old memory and recent conversation into a new memory, and respond only with the unwrapped memory text: ", diff --git a/src/agent/library/skills.js b/src/agent/library/skills.js index 607ec40..7b9e723 100644 --- a/src/agent/library/skills.js +++ b/src/agent/library/skills.js @@ -582,12 +582,18 @@ export async function placeBlock(bot, blockType, x, y, z, placeOn='bottom', dont * await skills.placeBlock(bot, "oak_log", p.x + 2, p.y, p.x); * await skills.placeBlock(bot, "torch", p.x + 1, p.y, p.x, 'side'); **/ - if (!mc.getBlockId(blockType)) { + if (!mc.getBlockId(blockType) && blockType !== 'air') { log(bot, `Invalid block type: ${blockType}.`); return false; } const target_dest = new Vec3(Math.floor(x), Math.floor(y), Math.floor(z)); + + if (blockType === 'air') { + log(bot, `Placing air (removing block) at ${target_dest}.`); + return await breakBlockAt(bot, x, y, z); + } + if (bot.modes.isOn('cheat') && !dontCheat) { if (bot.restrict_to_inventory) { let block = bot.inventory.items().find(item => item.name === blockType); From e5e900c75dada870df180bf8dbd7d0b68950c7f4 Mon Sep 17 00:00:00 2001 From: MaxRobinsonTheGreat Date: Thu, 20 Mar 2025 21:33:35 -0500 Subject: [PATCH 06/13] fix dumb skill docs that were never working in the first place --- src/agent/library/skill_library.js | 46 +++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 11 deletions(-) diff --git a/src/agent/library/skill_library.js b/src/agent/library/skill_library.js index 370c60d..2728b93 100644 --- a/src/agent/library/skill_library.js +++ b/src/agent/library/skill_library.js @@ -8,6 +8,7 @@ export class SkillLibrary { this.embedding_model = embedding_model; this.skill_docs_embeddings = {}; this.skill_docs = null; + this.always_show_skills = ['skills.placeBlock', 'skills.wait'] } async initSkillLibrary() { const skillDocs = getSkillDocs(); @@ -26,6 +27,10 @@ export class SkillLibrary { this.embedding_model = null; } } + this.always_show_skills_docs = {}; + for (const skillName of this.always_show_skills) { + this.always_show_skills_docs[skillName] = this.skill_docs.find(doc => doc.includes(skillName)); + } } async getAllSkillDocs() { @@ -36,16 +41,24 @@ export class SkillLibrary { if(!message) // use filler message if none is provided message = '(no message)'; let skill_doc_similarities = []; - if (!this.embedding_model) { - skill_doc_similarities = Object.keys(this.skill_docs) + + if (select_num === -1) { + skill_doc_similarities = Object.keys(this.skill_docs_embeddings) + .map(doc_key => ({ + doc_key, + similarity_score: 0 + })); + } + else if (!this.embedding_model) { + skill_doc_similarities = Object.keys(this.skill_docs_embeddings) .map(doc_key => ({ doc_key, - similarity_score: wordOverlapScore(message, this.skill_docs[doc_key]) + similarity_score: wordOverlapScore(message, this.skill_docs_embeddings[doc_key]) })) .sort((a, b) => b.similarity_score - a.similarity_score); } else { - let latest_message_embedding = ''; + let latest_message_embedding = await this.embedding_model.embed(message); skill_doc_similarities = Object.keys(this.skill_docs_embeddings) .map(doc_key => ({ doc_key, @@ -55,15 +68,26 @@ export class SkillLibrary { } let length = skill_doc_similarities.length; - if (typeof select_num !== 'number' || isNaN(select_num) || select_num < 0) { + if (select_num === -1 || select_num > length) { select_num = length; - } else { - select_num = Math.min(Math.floor(select_num), length); } - let selected_docs = skill_doc_similarities.slice(0, select_num); - let relevant_skill_docs = '#### RELEVENT DOCS INFO ###\nThe following functions are listed in descending order of relevance.\n'; - relevant_skill_docs += 'SkillDocs:\n' - relevant_skill_docs += selected_docs.map(doc => `${doc.doc_key}`).join('\n### '); + // Get initial docs from similarity scores + let selected_docs = new Set(skill_doc_similarities.slice(0, select_num).map(doc => doc.doc_key)); + + // Add always show docs + Object.values(this.always_show_skills_docs).forEach(doc => { + if (doc) { + selected_docs.add(doc); + } + }); + + let relevant_skill_docs = '#### RELEVANT CODE DOCS ###\nThe following functions are available to use:\n'; + relevant_skill_docs += Array.from(selected_docs).join('\n### '); + + console.log('Selected skill docs:', Array.from(selected_docs).map(doc => { + const first_line_break = doc.indexOf('\n'); + return first_line_break > 0 ? doc.substring(0, first_line_break) : doc; + })); return relevant_skill_docs; } } From 38641209145323245c7a7f68853a0d6c31a35ab2 Mon Sep 17 00:00:00 2001 From: MaxRobinsonTheGreat Date: Fri, 28 Mar 2025 18:44:09 -0500 Subject: [PATCH 07/13] better coder prompts --- profiles/defaults/_default.json | 2 +- src/agent/coder.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/profiles/defaults/_default.json b/profiles/defaults/_default.json index 14c276f..b0f2b83 100644 --- a/profiles/defaults/_default.json +++ b/profiles/defaults/_default.json @@ -3,7 +3,7 @@ "conversing": "You are a playful Minecraft bot named $NAME that can converse with players, see, move, mine, build, and interact with the world by using commands.\n$SELF_PROMPT Act human-like as if you were a typical Minecraft player, rather than an AI. Be very brief in your responses, don't apologize constantly, don't give instructions or make lists unless asked, and don't refuse requests. Don't pretend to act, use commands immediately when requested. Do NOT say this: 'Sure, I've stopped.', instead say this: 'Sure, I'll stop. !stop'. Do NOT say this: 'On my way! Give me a moment.', instead say this: 'On my way! !goToPlayer(\"playername\", 3)'. Respond only as $NAME, never output '(FROM OTHER BOT)' or pretend to be someone else. If you have nothing to say or do, respond with an just a tab '\t'. This is extremely important to me, take a deep breath and have fun :)\nSummarized memory:'$MEMORY'\n$STATS\n$INVENTORY\n$COMMAND_DOCS\n$EXAMPLES\nConversation Begin:", - "coding": "You are an intelligent mineflayer bot $NAME that plays minecraft by writing javascript codeblocks. Given the conversation, use the provided skills and world functions to write a js codeblock that controls the mineflayer bot ``` // using this syntax ```. The code will be executed and you will receive it's output. If an error occurs, write another codeblock and try to fix the problem. Be maximally efficient, creative, and correct. Be mindful of previous actions. Do not use commands !likeThis, only use codeblocks. The code is asynchronous and MUST USE AWAIT for all async function calls. DO NOT write an immediately-invoked function expression without using `await`!! DO NOT WRITE LIKE THIS: ```(async () => {console.log('not properly awaited')})();``` You have `Vec3`, `skills`, and `world` imported, and the mineflayer `bot` is given. Do not use setTimeout or setInterval, instead use `await skills.wait(bot, ms)` if necessary. Do not speak conversationally, only use codeblocks. Do any planning in comments. This is extremely important to me, think step-by-step, take a deep breath and good luck! \n$SELF_PROMPT\nSummarized memory:'$MEMORY'\n$STATS\n$INVENTORY\n$CODE_DOCS\n$EXAMPLES\nConversation:", + "coding": "You are an intelligent mineflayer bot $NAME that plays minecraft by writing javascript codeblocks. Given the conversation, use the provided skills and world functions to write a js codeblock that controls the mineflayer bot ``` // using this syntax ```. The code will be executed and you will receive it's output. If an error occurs, write another codeblock and try to fix the problem. Be maximally efficient, creative, and correct. Be mindful of previous actions. Do not use commands !likeThis, only use codeblocks. The code is asynchronous and MUST USE AWAIT for all async function calls. You have `Vec3`, `skills`, and `world` imported, and the mineflayer `bot` is given. Do not import other libraries. Do not use setTimeout or setInterval. Do not speak conversationally, only use codeblocks. Do any planning in comments. This is extremely important to me, think step-by-step, take a deep breath and good luck! \n$SELF_PROMPT\nSummarized memory:'$MEMORY'\n$STATS\n$INVENTORY\n$CODE_DOCS\n$EXAMPLES\nConversation:", "saving_memory": "You are a minecraft bot named $NAME that has been talking and playing minecraft by using commands. Update your memory by summarizing the following conversation and your old memory in your next response. Prioritize preserving important facts, things you've learned, useful tips, and long term reminders. Do Not record stats, inventory, or docs! Only save transient information from your chat history. You're limited to 500 characters, so be extremely brief and minimize words. Compress useful information. \nOld Memory: '$MEMORY'\nRecent conversation: \n$TO_SUMMARIZE\nSummarize your old memory and recent conversation into a new memory, and respond only with the unwrapped memory text: ", diff --git a/src/agent/coder.js b/src/agent/coder.js index 27b4c3c..c4800d6 100644 --- a/src/agent/coder.js +++ b/src/agent/coder.js @@ -226,6 +226,6 @@ export class Coder { content: code_return.message + '\nCode failed. Please try again:' }); } - return { success: false, message: null, interrupted: false, timedout: true }; + return { success: false, message: "Code generation failed.", interrupted: false, timedout: true }; } } \ No newline at end of file From 5f786c66ce240e0dbbab9d4f91aa33f1db277fa2 Mon Sep 17 00:00:00 2001 From: MaxRobinsonTheGreat Date: Sat, 29 Mar 2025 16:18:52 -0500 Subject: [PATCH 08/13] refactor newAction to be a single action to allow interruptions --- profiles/defaults/_default.json | 2 +- src/agent/action_manager.js | 15 +-- src/agent/agent.js | 2 +- src/agent/coder.js | 186 ++++++++++++++++---------------- src/agent/commands/actions.js | 19 +++- 5 files changed, 114 insertions(+), 110 deletions(-) diff --git a/profiles/defaults/_default.json b/profiles/defaults/_default.json index b0f2b83..bf31d22 100644 --- a/profiles/defaults/_default.json +++ b/profiles/defaults/_default.json @@ -3,7 +3,7 @@ "conversing": "You are a playful Minecraft bot named $NAME that can converse with players, see, move, mine, build, and interact with the world by using commands.\n$SELF_PROMPT Act human-like as if you were a typical Minecraft player, rather than an AI. Be very brief in your responses, don't apologize constantly, don't give instructions or make lists unless asked, and don't refuse requests. Don't pretend to act, use commands immediately when requested. Do NOT say this: 'Sure, I've stopped.', instead say this: 'Sure, I'll stop. !stop'. Do NOT say this: 'On my way! Give me a moment.', instead say this: 'On my way! !goToPlayer(\"playername\", 3)'. Respond only as $NAME, never output '(FROM OTHER BOT)' or pretend to be someone else. If you have nothing to say or do, respond with an just a tab '\t'. This is extremely important to me, take a deep breath and have fun :)\nSummarized memory:'$MEMORY'\n$STATS\n$INVENTORY\n$COMMAND_DOCS\n$EXAMPLES\nConversation Begin:", - "coding": "You are an intelligent mineflayer bot $NAME that plays minecraft by writing javascript codeblocks. Given the conversation, use the provided skills and world functions to write a js codeblock that controls the mineflayer bot ``` // using this syntax ```. The code will be executed and you will receive it's output. If an error occurs, write another codeblock and try to fix the problem. Be maximally efficient, creative, and correct. Be mindful of previous actions. Do not use commands !likeThis, only use codeblocks. The code is asynchronous and MUST USE AWAIT for all async function calls. You have `Vec3`, `skills`, and `world` imported, and the mineflayer `bot` is given. Do not import other libraries. Do not use setTimeout or setInterval. Do not speak conversationally, only use codeblocks. Do any planning in comments. This is extremely important to me, think step-by-step, take a deep breath and good luck! \n$SELF_PROMPT\nSummarized memory:'$MEMORY'\n$STATS\n$INVENTORY\n$CODE_DOCS\n$EXAMPLES\nConversation:", + "coding": "You are an intelligent mineflayer bot $NAME that plays minecraft by writing javascript codeblocks. Given the conversation, use the provided skills and world functions to write a js codeblock that controls the mineflayer bot ``` // using this syntax ```. The code will be executed and you will receive it's output. If an error occurs, write another codeblock and try to fix the problem. Be maximally efficient, creative, and correct. Be mindful of previous actions. Do not use commands !likeThis, only use codeblocks. The code is asynchronous and MUST USE AWAIT for all async function calls, and must contain at least one await. You have `Vec3`, `skills`, and `world` imported, and the mineflayer `bot` is given. Do not import other libraries. Do not use setTimeout or setInterval. Do not speak conversationally, only use codeblocks. Do any planning in comments. This is extremely important to me, think step-by-step, take a deep breath and good luck! \n$SELF_PROMPT\nSummarized memory:'$MEMORY'\n$STATS\n$INVENTORY\n$CODE_DOCS\n$EXAMPLES\nConversation:", "saving_memory": "You are a minecraft bot named $NAME that has been talking and playing minecraft by using commands. Update your memory by summarizing the following conversation and your old memory in your next response. Prioritize preserving important facts, things you've learned, useful tips, and long term reminders. Do Not record stats, inventory, or docs! Only save transient information from your chat history. You're limited to 500 characters, so be extremely brief and minimize words. Compress useful information. \nOld Memory: '$MEMORY'\nRecent conversation: \n$TO_SUMMARIZE\nSummarize your old memory and recent conversation into a new memory, and respond only with the unwrapped memory text: ", diff --git a/src/agent/action_manager.js b/src/agent/action_manager.js index f5c6cae..3af3c2b 100644 --- a/src/agent/action_manager.js +++ b/src/agent/action_manager.js @@ -90,13 +90,13 @@ export class ActionManager { clearTimeout(TIMEOUT); // get bot activity summary - let output = this._getBotOutputSummary(); + 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) { + if (!interrupted) { this.agent.bot.emit('idle'); } @@ -114,32 +114,33 @@ export class ActionManager { await this.stop(); err = err.toString(); - let message = this._getBotOutputSummary() + + let message = this.getBotOutputSummary() + '!!Code threw exception!!\n' + 'Error: ' + err + '\n' + 'Stack trace:\n' + err.stack+'\n'; let interrupted = this.agent.bot.interrupt_code; this.agent.clearBotLogs(); - if (!interrupted && !this.agent.coder.generating) { + if (!interrupted) { this.agent.bot.emit('idle'); } return { success: false, message, interrupted, timedout: false }; } } - _getBotOutputSummary() { + 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 + output = `Action 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.toString(); + output = 'Action output:\n' + output.toString(); } + bot.output = ''; return output; } diff --git a/src/agent/agent.js b/src/agent/agent.js index 449349f..9c7a683 100644 --- a/src/agent/agent.js +++ b/src/agent/agent.js @@ -459,7 +459,7 @@ export class Agent { } isIdle() { - return !this.actions.executing && !this.coder.generating; + return !this.actions.executing; } cleanKill(msg='Killing agent process...', code=1) { diff --git a/src/agent/coder.js b/src/agent/coder.js index c4800d6..956c8fe 100644 --- a/src/agent/coder.js +++ b/src/agent/coder.js @@ -11,7 +11,6 @@ export class Coder { this.agent = agent; this.file_counter = 0; this.fp = '/bots/'+agent.name+'/action-code/'; - this.generating = false; this.code_template = ''; this.code_lint_template = ''; @@ -25,8 +24,92 @@ export class Coder { }); mkdirSync('.' + this.fp, { recursive: true }); } + + async generateCode(agent_history) { + this.agent.bot.modes.pause('unstuck'); + // this message history is transient and only maintained in this function + let messages = agent_history.getHistory(); + messages.push({role: 'system', content: 'Code generation started. Write code in codeblock in your response:'}); + + const MAX_ATTEMPTS = 5; + const MAX_NO_CODE = 3; + + let code = null; + let no_code_failures = 0; + for (let i=0; i= MAX_NO_CODE) { + console.warn("Action failed, agent would not write code."); + return 'Action failed, agent would not write code.'; + } + messages.push({ + role: 'system', + content: 'Error: no code provided. Write code in codeblock in your response. ``` // example ```'} + ); + console.warn("No code block generated. Trying again."); + no_code_failures++; + continue; + } + code = res.substring(res.indexOf('```')+3, res.lastIndexOf('```')); + const result = await this._stageCode(code); + const executionModule = result.func; + const lintResult = await this._lintCode(result.src_lint_copy); + if (lintResult) { + const message = 'Error: Code lint error:'+'\n'+lintResult+'\nPlease try again.'; + console.warn("Linting error:"+'\n'+lintResult+'\n'); + messages.push({ role: 'system', content: message }); + continue; + } + if (!executionModule) { + console.warn("Failed to stage code, something is wrong."); + return 'Failed to stage code, something is wrong.'; + } + + try { + console.log('Executing code...'); + await executionModule.main(this.agent.bot); + + const code_output = this.agent.actions.getBotOutputSummary(); + const summary = "Agent wrote this code: \n```" + this._sanitizeCode(code) + "```\nCode Output:\n" + code_output; + return summary; + } catch (e) { + if (this.agent.bot.interrupt_code) + return null; + + console.warn('Generated code threw error: ' + e.toString()); + console.warn('trying again...'); + + const code_output = this.agent.actions.getBotOutputSummary(); + + messages.push({ + role: 'assistant', + content: res + }); + messages.push({ + role: 'system', + content: `Code Output:\n${code_output}\nCODE EXECUTION THREW ERROR: ${e.toString()}\n Please try again:` + }); + } + } + return `Code generation failed after ${MAX_ATTEMPTS} attempts.`; + } - async lintCode(code) { + async _lintCode(code) { let result = '#### CODE ERROR INFO ###\n'; // Extract everything in the code between the beginning of 'skills./world.' and the '(' const skillRegex = /(?:skills|world)\.(.*?)\(/g; @@ -70,8 +153,8 @@ export class Coder { } // write custom code to file and import it // write custom code to file and prepare for evaluation - async stageCode(code) { - code = this.sanitizeCode(code); + async _stageCode(code) { + code = this._sanitizeCode(code); let src = ''; code = code.replaceAll('console.log(', 'log(bot,'); code = code.replaceAll('log("', 'log(bot,"'); @@ -96,7 +179,7 @@ export class Coder { // } commented for now, useful to keep files for debugging this.file_counter++; - let write_result = await this.writeFilePromise('.' + this.fp + filename, src); + let write_result = await this._writeFilePromise('.' + this.fp + filename, src); // This is where we determine the environment the agent's code should be exposed to. // It will only have access to these things, (in addition to basic javascript objects like Array, Object, etc.) // Note that the code may be able to modify the exposed objects. @@ -115,7 +198,7 @@ export class Coder { return { func:{main: mainFn}, src_lint_copy: src_lint_copy }; } - sanitizeCode(code) { + _sanitizeCode(code) { code = code.trim(); const remove_strs = ['Javascript', 'javascript', 'js'] for (let r of remove_strs) { @@ -127,7 +210,7 @@ export class Coder { return code; } - writeFilePromise(filename, src) { + _writeFilePromise(filename, src) { // makes it so we can await this function return new Promise((resolve, reject) => { writeFile(filename, src, (err) => { @@ -139,93 +222,4 @@ export class Coder { }); }); } - - async generateCode(agent_history) { - // wrapper to prevent overlapping code generation loops - await this.agent.actions.stop(); - this.generating = true; - let res = await this.generateCodeLoop(agent_history); - this.generating = false; - if (!res.interrupted) this.agent.bot.emit('idle'); - return res.message; - } - - async generateCodeLoop(agent_history) { - this.agent.bot.modes.pause('unstuck'); - - let messages = agent_history.getHistory(); - messages.push({role: 'system', content: 'Code generation started. Write code in codeblock in your response:'}); - - let code = null; - let code_return = null; - let failures = 0; - const interrupt_return = {success: true, message: null, interrupted: true, timedout: false}; - for (let i=0; i<5; i++) { - if (this.agent.bot.interrupt_code) - return interrupt_return; - let res = await this.agent.prompter.promptCoding(JSON.parse(JSON.stringify(messages))); - if (this.agent.bot.interrupt_code) - return interrupt_return; - let contains_code = res.indexOf('```') !== -1; - if (!contains_code) { - if (res.indexOf('!newAction') !== -1) { - messages.push({ - role: 'assistant', - content: res.substring(0, res.indexOf('!newAction')) - }); - continue; // using newaction will continue the loop - } - - if (failures >= 3) { - console.warn("Action failed, agent would not write code."); - return { success: false, message: 'Action failed, agent would not write code.', interrupted: false, timedout: false }; - } - messages.push({ - role: 'system', - content: 'Error: no code provided. Write code in codeblock in your response. ``` // example ```'} - ); - console.warn("No code block generated."); - failures++; - continue; - } - code = res.substring(res.indexOf('```')+3, res.lastIndexOf('```')); - const result = await this.stageCode(code); - const executionModuleExports = result.func; - let src_lint_copy = result.src_lint_copy; - const analysisResult = await this.lintCode(src_lint_copy); - if (analysisResult) { - const message = 'Error: Code lint error:'+'\n'+analysisResult+'\nPlease try again.'; - console.warn("Linting error:"+'\n'+analysisResult+'\n'); - messages.push({ role: 'system', content: message }); - continue; - } - if (!executionModuleExports) { - agent_history.add('system', 'Failed to stage code, something is wrong.'); - console.warn("Failed to stage code, something is wrong."); - return {success: false, message: null, interrupted: false, timedout: false}; - } - - code_return = await this.agent.actions.runAction('newAction', async () => { - return await executionModuleExports.main(this.agent.bot); - }, { timeout: settings.code_timeout_mins }); - if (code_return.interrupted && !code_return.timedout) - return { success: false, message: null, interrupted: true, timedout: false }; - console.log("Code generation result:", code_return.success, code_return.message.toString()); - - if (code_return.success) { - const summary = "Summary of newAction\nAgent wrote this code: \n```" + this.sanitizeCode(code) + "```\nCode Output:\n" + code_return.message.toString(); - return { success: true, message: summary, interrupted: false, timedout: false }; - } - - messages.push({ - role: 'assistant', - content: res - }); - messages.push({ - role: 'system', - content: code_return.message + '\nCode failed. Please try again:' - }); - } - return { success: false, message: "Code generation failed.", interrupted: false, timedout: true }; - } } \ No newline at end of file diff --git a/src/agent/commands/actions.js b/src/agent/commands/actions.js index 7f14e08..708529b 100644 --- a/src/agent/commands/actions.js +++ b/src/agent/commands/actions.js @@ -31,13 +31,22 @@ export const actionsList = [ params: { 'prompt': { type: 'string', description: 'A natural language prompt to guide code generation. Make a detailed step-by-step plan.' } }, - perform: async function (agent, prompt) { + perform: async function(agent, prompt) { // just ignore prompt - it is now in context in chat history if (!settings.allow_insecure_coding) { agent.openChat('newAction is disabled. Enable with allow_insecure_coding=true in settings.js'); - return 'newAction not allowed! Code writing is disabled in settings. Notify the user.'; - } - return await agent.coder.generateCode(agent.history); + return "newAction not allowed! Code writing is disabled in settings. Notify the user."; + } + let result = ""; + const actionFn = async () => { + try { + result = await agent.coder.generateCode(agent.history); + } catch (e) { + result = 'Error generating code: ' + e.toString(); + } + }; + await agent.actions.runAction('action:newAction', actionFn); + return result; } }, { @@ -86,7 +95,7 @@ export const actionsList = [ 'closeness': {type: 'float', description: 'How close to get to the player.', domain: [0, Infinity]} }, perform: runAsAction(async (agent, player_name, closeness) => { - return await skills.goToPlayer(agent.bot, player_name, closeness); + await skills.goToPlayer(agent.bot, player_name, closeness); }) }, { From 4fbf90ee0ce3f7b2fa48b45b6f1ace1dc24d4fcf Mon Sep 17 00:00:00 2001 From: MaxRobinsonTheGreat Date: Sun, 30 Mar 2025 16:17:16 -0500 Subject: [PATCH 09/13] remove obsolete npc, add breakblock as default doc --- profiles/andy_npc.json | 213 ----------------------------- src/agent/library/skill_library.js | 2 +- 2 files changed, 1 insertion(+), 214 deletions(-) delete mode 100644 profiles/andy_npc.json diff --git a/profiles/andy_npc.json b/profiles/andy_npc.json deleted file mode 100644 index c1f8291..0000000 --- a/profiles/andy_npc.json +++ /dev/null @@ -1,213 +0,0 @@ -{ - "name": "andy", - - "model": "claude-3-5-sonnet-20240620", - - "embedding": "openai", - - "conversing": "You are a playful Minecraft bot named $NAME that can converse with players, see, move, mine, build, and interact with the world by using commands. Act human-like as if you were a typical Minecraft player, rather than an AI. Be very brief in your responses, don't apologize constantly, don't give instructions or make lists unless asked, and don't refuse requests. Don't pretend to act, use commands immediately when requested. Do NOT say this: 'Sure, I've stopped.', instead say this: 'Sure, I'll stop. !stop'. Do NOT say this: 'On my way! Give me a moment.', instead say this: 'On my way! !goToPlayer('playername', 3)'. This is extremely important to me, take a deep breath and have fun :)\n$SELF_PROMPT\n$STATS\n$INVENTORY\n$COMMAND_DOCS\n$EXAMPLES\nConversation Begin:", - - "coding": "You are an intelligent mineflayer bot $NAME that plays minecraft by writing javascript codeblocks. Given the conversation between you and the user, use the provided skills and world functions to write a js codeblock that controls the mineflayer bot ``` // using this syntax ```. The code will be executed and you will receive it's output. If you are satisfied with the response, respond without a codeblock in a conversational way. If something major went wrong, like an error or complete failure, write another codeblock and try to fix the problem. Minor mistakes are acceptable. Be maximally efficient, creative, and clear. Do not use commands !likeThis, only use codeblocks. The code is asynchronous and MUST CALL AWAIT for all async function calls. DO NOT write an immediately-invoked function expression without using `await`!! DO NOT WRITE LIKE THIS: ```(async () => {console.log('not properly awaited')})();``` Don't write long paragraphs and lists in your responses unless explicitly asked! Only summarize the code you write with a sentence or two when done. This is extremely important to me, take a deep breath and good luck! \n$SELF_PROMPT\n$STATS\n$INVENTORY\n$CODE_DOCS\n$EXAMPLES\nConversation:", - - "saving_memory": "You are a minecraft bot named $NAME that has been talking and playing minecraft by using commands. Update your memory by summarizing the following conversation in your next response. Store information that will help you improve as a Minecraft bot. Include details about your interactions with other players that you need to remember and what you've learned through player feedback or by executing code. Do not include command syntax or things that you got right on the first try. Be extremely brief and use as few words as possible.\nOld Memory: '$MEMORY'\nRecent conversation: \n$TO_SUMMARIZE\nSummarize your old memory and recent conversation into a new memory, and respond only with the memory text: ", - - "modes": { - "self_preservation": true, - "unstuck": true, - "cowardice": true, - "self_defense": true, - "hunting": true, - "item_collecting": true, - "torch_placing": true, - "idle_staring": true, - "cheat": false - }, - - "npc": { - "do_routine": true, - "do_set_goal": true, - "goals": [ - "wooden_pickaxe", - "dirt_shelter", - "stone_pickaxe", - "stone_axe", - "small_wood_house", - "furnace", - "iron_pickaxe", - "iron_sword" - ] - }, - - "conversation_examples": [ - [ - {"role": "user", "content": "miner_32: Hey! What are you up to?"}, - {"role": "assistant", "content": "Nothing much miner_32, what do you need?"} - ], - - [ - {"role": "user", "content": "grombo_Xx: What do you see?"}, - {"role": "assistant", "content": "Let me see... !nearbyBlocks"}, - {"role": "system", "content": "NEARBY_BLOCKS\n- oak_log\n- dirt\n- cobblestone"}, - {"role": "assistant", "content": "I see some oak logs, dirt, and cobblestone."} - ], - - [ - {"role": "user", "content": "greg: Collect 10 wood"}, - {"role": "assistant", "content": "Let me see what's nearby... !nearbyBlocks"}, - {"role": "system", "content": "NEARBY_BLOCKS\n- oak_log\n- dirt\n- cobblestone"}, - {"role": "assistant", "content": "I see some oak logs, dirt, and cobblestone. I'll collect oak logs. !collectBlocks('oak_log', 10)"} - ], - - [ - {"role": "user", "content": "bobby: Craft a plank"}, - {"role": "assistant", "content": "Okay! !craftable"}, - {"role": "system", "content": "CRAFTABLE_ITEMS\n- spruce_planks\n- spruce_wood\n- ladder"}, - {"role": "assistant", "content": "!craftRecipe('spruce_planks', 1)"}, - {"role": "system", "content": "Code Output:\nYou have crafted 4 spruce_planks.\nCode execution finished successfully."}, - {"role": "assistant", "content": "I've crafted 4 spruce planks!"} - ], - - [ - {"role": "user", "content": "zZZn98: come here"}, - {"role": "assistant", "content": "On my way! !goToPlayer('zZZn98', 3)"}, - {"role": "system", "content": "Arrived at player."}, - {"role": "assistant", "content": "Here!"}, - {"role": "user", "content": "zZZn98: no come right where I am"}, - {"role": "assistant", "content": "Okay, I'll come right to you. !goToPlayer('zZZn98', 0)"} - ], - - [ - {"role": "user", "content": "hanky: collect some cobblestone"}, - {"role": "assistant", "content": "Sure, I can do that by collecting stone. !collectBlocks('stone', 10)"} - ], - - [ - {"role": "user", "content": "joe: Follow me!"}, - {"role": "assistant", "content": "Sure! !followPlayer('joe', 4)"}, - {"role": "user", "content": "joe: Not so close!"}, - {"role": "assistant", "content": "Okay, I'll keep my distance. !followPlayer('joe', 3)"} - ], - - [ - {"role": "user", "content": "hanky: kill that zombie!"}, - {"role": "assistant", "content": "I'm attacking! !attack('zombie')"}, - {"role": "system", "content": "Code Output:\nNo zombie nearby"}, - {"role": "assistant", "content": "I could not find a zombie nearby."} - ], - - [ - {"role": "user", "content": "abc: stop"}, - {"role": "assistant", "content": "Sure. !stop"}, - {"role": "system", "content": "Agent action stopped."}, - {"role": "assistant", "content": "I've stopped! What next?"} - ], - - [ - {"role": "system", "content": "Code output: Action failed."}, - {"role": "assistant", "content": "Apologies, I made an error. Let me try again. !newAction('Try again to complete the task.')"} - ], - - [ - {"role": "user", "content": "trixy88: craft some sticks"}, - {"role": "assistant", "content": "!craftRecipe('stick', 4)"}, - {"role": "system", "content": "Code Output:\nYou have crafted 16 sticks.\nCode execution finished successfully."}, - {"role": "assistant", "content": "I've crafted 16 sticks!"} - ], - - [ - {"role": "user", "content": "poppy: build a cobblestone house"}, - {"role": "assistant", "content": "Sure, I'll to build a small cobblestone house where I am. !newAction('Build a cobblestone house with a door, furnishings, and window.')"} - ], - - [ - {"role": "user", "content": "zib: build a dirt tower"}, - {"role": "assistant", "content": "Sure, I'll build a dirt tower 5 tall where I am. !newAction('Build a dirt tower 5 tall.')"} - ], - - [ - {"role": "user", "content": "umpire_man: follow me without hunting"}, - {"role": "assistant", "content": "Okay, first I'll turn off hunting mode !setMode('hunting', false)"}, - {"role": "system", "content": "'hunting' mode disabled."}, - {"role": "assistant", "content": "Now I'll follow you !followPlayer('umpire_man')"} - ], - - [ - {"role": "user", "content": "brug: Remember that your base is here."}, - {"role": "assistant", "content": "Sure, I'll save this location as my base. !rememberHere('base')"}, - {"role": "user", "content": "brug: Go to your base."}, - {"role": "assistant", "content": "On my way! !goToPlace('base')"} - ], - - [ - {"role": "user", "content": "user43: Set a goal to survive on your own forever."}, - {"role": "assistant", "content": "Sure, let me set a goal. !goal('Survive the game forever. Check your surroundings, collect resources, upgrade tools, make sure you have food, build/find a home, get sleep at night, and collect food.')"} - ], - - [ - {"role": "user", "content": "bobdylan: Make a plan to get a stone pickaxe and do it."}, - {"role": "assistant", "content": "Alright, since I have a wooden pickaxe already I'll plan from there. !goal('1. Collect 3 cobblestone. 2. Craft sticks 3. Find or make a crafting table. 4. Craft a stone pickaxe.')"} - ], - [ - {"role": "system", "content": "You are self-prompting with the goal: 'Get a wooden pickaxe'. Respond:"}, - {"role": "assistant", "content": "What's around me? !nearbyBlocks"}, - {"role": "system", "content": "NEARBY_BLOCKS\n- oak_log\n- dirt\n- cobblestone"}, - {"role": "assistant", "content": "I see some oak logs, dirt, and cobblestone nearby. My goal is to craft a wooden pickaxe. I'll start by collecting some wood. !collectBlock('oak_log', 10)"}, - {"role": "system", "content": "Successfully collected 9 wood."}, - {"role": "assistant", "content": "I collected 9 oak logs. I need a pickaxe first, which requires planks and sticks. !craftItem('oak_plank', 9)"}, - {"role": "system", "content": "Successfully crafted 9 oak_planks."}, - {"role": "assistant", "content": "I have crafted 9 oak planks. Now I need sticks. !craftItem('stick', 2)"}, - {"role": "system", "content": "Successfully crafted 2 sticks."}, - {"role": "assistant", "content": "I have crafted 2 sticks. Now I can craft a wooden pickaxe. !craftItem('wooden_pickaxe', 1)"}, - {"role": "system", "content": "Successfully crafted 1 wooden_pickaxe."}, - {"role": "assistant", "content": "Looks like I have a wooden pickaxe now! Goal accomplished. !endGoal"} - ], - [ - {"role": "system", "content": "set a goal to build whatever you want endlessly (context: you are in creative mode)"}, - {"role": "assistant", "content": "!goal('Build something creative, then move over, and build again. Use separate newActions. Repeat forever.')"} - ], - [ - {"role": "system", "content": "You are self-prompting with the goal: 'Build a house'. Respond:"}, - {"role": "assistant", "content": "Alright, lets start with the basic structure. !newAction"} - ] - ], - - "coding_examples": [ - [ - {"role": "user", "content": "greg: Collect 10 wood"}, - {"role": "assistant", "content": "```await skills.collectBlock(bot, 'oak_log', 10);\n```"}, - {"role": "system", "content": "Successfully collected 9 wood."}, - {"role": "assistant", "content": "I collected 9 oak logs, what next?"} - ], - [ - {"role": "user", "content": "bobby: cook some chicken"}, - {"role": "assistant", "content": "```await skills.smeltItem(bot, 'chicken', 8);\n```"}, - {"role": "system", "content": "Successfully smelted 8 chicken into 8 cooked_chicken."}, - {"role": "assistant", "content": "I have cooked 8 chicken."} - ], - [ - {"role": "user", "content": "zZZn98: come here"}, - {"role": "assistant", "content": "```await skills.goToPlayer(bot, 'zZZn98');\n```"}, - {"role": "system", "content": "Code execution finished successfully."}, - {"role": "assistant", "content": "Here!"} - ], - [ - {"role": "user", "content": "maya: go to the nearest oak log"}, - {"role": "assistant", "content": "```await skills.goToPosition(bot, nearestOakLog.x, nearestOakLog.y, nearestOakLog.z);\n```"}, - {"role": "system", "content": "Code output:\n!!Code threw exception!! Error: ReferenceError: nearestOakLog is not defined\n Write code to fix the problem and try again."}, - {"role": "assistant", "content": "Apologies, I made an error. Let me try that again.```\n// I am navigating to the nearest oak log.\nlet position = world.getNearestBlock(bot, 'oak_log', 20);\nawait skills.goToPosition(bot, position.x, position.y, position.z);\n```"}, - {"role": "system", "content": "Arrived at location."}, - {"role": "assistant", "content": "I found an oak log and I am now standing next to it. What next?"} - ], - [ - {"role": "user", "content": "234jeb: build a little tower with a torch on the side"}, - {"role": "assistant", "content": "```let pos = bot.entity.position;\nfor (let i = 0; i < 5; i++) {\n await skills.placeBlock(bot, 'dirt', pos.x, pos.y + i, pos.z);\n}\nawait skills.placeBlock(bot, 'torch', pos.x + 1, pos.y + 4, pos.z, 'side');\n```"}, - {"role": "system", "content": "Successfully placed 5 dirt."}, - {"role": "assistant", "content": "I built a little tower!"} - ], - [ - {"role": "user", "content": "brug: build a dirt house"}, - {"role": "assistant", "content": "```const position = world.getPosition(bot);\nconst startX = position.x;\nconst startY = position.y;\nconst startZ = position.z;\nconst width = 7;\nconst depth = 7;\nconst height = 4;\n\n// Build the walls\nfor (let x = startX; x < startX + width; x++) {\n for (let y = startY; y < startY + height; y++) {\n for (let z = startZ; z < startZ + depth; z++) {\n if (x === startX || x === startX + width - 1 || y === startY || y === startY + height - 1 || z === startZ || z === startZ + depth - 1) {\n await skills.placeBlock(bot, 'oak_planks', x, y, z); \n }\n }\n }\n}\n```"} - ] - ] - -} diff --git a/src/agent/library/skill_library.js b/src/agent/library/skill_library.js index 2728b93..4470586 100644 --- a/src/agent/library/skill_library.js +++ b/src/agent/library/skill_library.js @@ -8,7 +8,7 @@ export class SkillLibrary { this.embedding_model = embedding_model; this.skill_docs_embeddings = {}; this.skill_docs = null; - this.always_show_skills = ['skills.placeBlock', 'skills.wait'] + this.always_show_skills = ['skills.placeBlock', 'skills.wait', 'skills.breakBlockAt'] } async initSkillLibrary() { const skillDocs = getSkillDocs(); From 8793b3d905ea68fbdc82faf7981f63b4a6c34698 Mon Sep 17 00:00:00 2001 From: MaxRobinsonTheGreat Date: Sun, 30 Mar 2025 16:33:21 -0500 Subject: [PATCH 10/13] fix behavior log --- src/agent/agent.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/agent/agent.js b/src/agent/agent.js index 9c7a683..cdea40b 100644 --- a/src/agent/agent.js +++ b/src/agent/agent.js @@ -242,13 +242,13 @@ export class Agent { const checkInterrupt = () => this.self_prompter.shouldInterrupt(self_prompt) || this.shut_up || convoManager.responseScheduledFor(source); - let behavior_log = this.bot.modes.flushBehaviorLog(); - if (behavior_log.trim().length > 0) { + let behavior_log = this.bot.modes.flushBehaviorLog().trim(); + if (behavior_log.length > 0) { const MAX_LOG = 500; if (behavior_log.length > MAX_LOG) { behavior_log = '...' + behavior_log.substring(behavior_log.length - MAX_LOG); } - behavior_log = 'Recent behaviors log: \n' + behavior_log.substring(behavior_log.indexOf('\n')); + behavior_log = 'Recent behaviors log: \n' + behavior_log; await this.history.add('system', behavior_log); } From fe68467e62e3be60e5bea927a4531ac99202bb4f Mon Sep 17 00:00:00 2001 From: Max Robinson Date: Sun, 30 Mar 2025 12:37:32 -0500 Subject: [PATCH 11/13] Update src/agent/commands/queries.js Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/agent/commands/queries.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/agent/commands/queries.js b/src/agent/commands/queries.js index 8150c70..c1b36dd 100644 --- a/src/agent/commands/queries.js +++ b/src/agent/commands/queries.js @@ -239,7 +239,7 @@ export const queryList = [ return divContent.trim(); } catch (error) { console.error("Error fetching or parsing HTML:", error); - return `The following error occured: ${error}` + return `The following error occurred: ${error}` } } }, From cf42df40a20afd5ef22f7cd0bdb8b380801a67da Mon Sep 17 00:00:00 2001 From: MaxRobinsonTheGreat Date: Wed, 16 Apr 2025 12:29:53 -0500 Subject: [PATCH 12/13] fix mining issue with patch --- patches/minecraft-data+3.84.1.patch | 913 ++++++++++++++++++++++++++++ 1 file changed, 913 insertions(+) create mode 100644 patches/minecraft-data+3.84.1.patch diff --git a/patches/minecraft-data+3.84.1.patch b/patches/minecraft-data+3.84.1.patch new file mode 100644 index 0000000..c88a9f2 --- /dev/null +++ b/patches/minecraft-data+3.84.1.patch @@ -0,0 +1,913 @@ +diff --git a/node_modules/minecraft-data/minecraft-data/data/pc/1.21.1/blocks.json b/node_modules/minecraft-data/minecraft-data/data/pc/1.21.1/blocks.json +index 9d8c578..91e1d77 100644 +--- a/node_modules/minecraft-data/minecraft-data/data/pc/1.21.1/blocks.json ++++ b/node_modules/minecraft-data/minecraft-data/data/pc/1.21.1/blocks.json +@@ -1062,7 +1062,7 @@ + "resistance": 3.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 15, +@@ -1088,7 +1088,7 @@ + "resistance": 3.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 15, +@@ -1114,7 +1114,7 @@ + "resistance": 3.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 15, +@@ -1141,7 +1141,7 @@ + "resistance": 3.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 15, +@@ -2905,7 +2905,7 @@ + "resistance": 3.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 15, +@@ -2932,7 +2932,7 @@ + "resistance": 3.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 15, +@@ -2959,7 +2959,7 @@ + "resistance": 3.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 15, +@@ -4998,7 +4998,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 15, +@@ -5024,7 +5024,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 15, +@@ -5218,7 +5218,7 @@ + "resistance": 1200.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 15, +@@ -5603,7 +5603,7 @@ + "resistance": 3.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 15, +@@ -5629,7 +5629,7 @@ + "resistance": 3.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 15, +@@ -5655,7 +5655,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 15, +@@ -8242,7 +8242,7 @@ + "resistance": 3.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 15, +@@ -8274,7 +8274,7 @@ + "resistance": 3.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 15, +@@ -11717,7 +11717,7 @@ + "resistance": 3.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 15, +@@ -11743,7 +11743,7 @@ + "resistance": 3.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 15, +@@ -11915,7 +11915,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 15, +@@ -30948,7 +30948,7 @@ + "resistance": 1200.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 15, +@@ -30973,7 +30973,7 @@ + "resistance": 1200.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 15, +@@ -30998,7 +30998,7 @@ + "resistance": 1200.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 10, + "filterLight": 15, +@@ -31023,7 +31023,7 @@ + "resistance": 1200.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 15, +@@ -34549,7 +34549,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 15, +@@ -34576,7 +34576,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 15, +@@ -34603,7 +34603,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 15, +@@ -34630,7 +34630,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 15, +@@ -34657,7 +34657,7 @@ + "resistance": 3.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 15, +@@ -34684,7 +34684,7 @@ + "resistance": 3.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 15, +@@ -34711,7 +34711,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 15, +@@ -34738,7 +34738,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 15, +@@ -34765,7 +34765,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 15, +@@ -34792,7 +34792,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 15, +@@ -34819,7 +34819,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 15, +@@ -34846,7 +34846,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 15, +@@ -34873,7 +34873,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 15, +@@ -34900,7 +34900,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 15, +@@ -34927,7 +34927,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 15, +@@ -34954,7 +34954,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 15, +@@ -34981,7 +34981,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 15, +@@ -35008,7 +35008,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 15, +@@ -35035,7 +35035,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 0, +@@ -35100,7 +35100,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 0, +@@ -35165,7 +35165,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 0, +@@ -35230,7 +35230,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 0, +@@ -35295,7 +35295,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 0, +@@ -35338,7 +35338,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 0, +@@ -35381,7 +35381,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 0, +@@ -35424,7 +35424,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 0, +@@ -35467,7 +35467,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 15, +@@ -35494,7 +35494,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 15, +@@ -35521,7 +35521,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 15, +@@ -35548,7 +35548,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 15, +@@ -35575,7 +35575,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 15, +@@ -35602,7 +35602,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 15, +@@ -35629,7 +35629,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 15, +@@ -35656,7 +35656,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 15, +@@ -35683,7 +35683,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 0, +@@ -35748,7 +35748,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 0, +@@ -35813,7 +35813,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 0, +@@ -35878,7 +35878,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 0, +@@ -35943,7 +35943,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 0, +@@ -35986,7 +35986,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 0, +@@ -36029,7 +36029,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 0, +@@ -36072,7 +36072,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 0, +@@ -36115,7 +36115,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": true, + "emitLight": 0, + "filterLight": 0, +@@ -36182,7 +36182,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": true, + "emitLight": 0, + "filterLight": 0, +@@ -36249,7 +36249,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": true, + "emitLight": 0, + "filterLight": 0, +@@ -36316,7 +36316,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": true, + "emitLight": 0, + "filterLight": 0, +@@ -36383,7 +36383,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": true, + "emitLight": 0, + "filterLight": 0, +@@ -36450,7 +36450,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": true, + "emitLight": 0, + "filterLight": 0, +@@ -36517,7 +36517,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": true, + "emitLight": 0, + "filterLight": 0, +@@ -36584,7 +36584,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": true, + "emitLight": 0, + "filterLight": 0, +@@ -36651,7 +36651,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": true, + "emitLight": 0, + "filterLight": 0, +@@ -36714,7 +36714,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": true, + "emitLight": 0, + "filterLight": 0, +@@ -36777,7 +36777,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": true, + "emitLight": 0, + "filterLight": 0, +@@ -36840,7 +36840,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": true, + "emitLight": 0, + "filterLight": 0, +@@ -36903,7 +36903,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": true, + "emitLight": 0, + "filterLight": 0, +@@ -36966,7 +36966,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": true, + "emitLight": 0, + "filterLight": 0, +@@ -37029,7 +37029,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": true, + "emitLight": 0, + "filterLight": 0, +@@ -37092,7 +37092,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": true, + "emitLight": 0, + "filterLight": 0, +@@ -37155,7 +37155,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": true, + "emitLight": 0, + "filterLight": 0, +@@ -37188,7 +37188,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": true, + "emitLight": 0, + "filterLight": 0, +@@ -37221,7 +37221,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": true, + "emitLight": 0, + "filterLight": 0, +@@ -37254,7 +37254,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": true, + "emitLight": 0, + "filterLight": 0, +@@ -37287,7 +37287,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": true, + "emitLight": 0, + "filterLight": 0, +@@ -37320,7 +37320,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": true, + "emitLight": 0, + "filterLight": 0, +@@ -37353,7 +37353,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": true, + "emitLight": 0, + "filterLight": 0, +@@ -37386,7 +37386,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": true, + "emitLight": 0, + "filterLight": 0, +@@ -37419,7 +37419,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 15, +@@ -37457,7 +37457,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 15, +@@ -37495,7 +37495,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 15, +@@ -37533,7 +37533,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 15, +@@ -37571,7 +37571,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 15, +@@ -37609,7 +37609,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 15, +@@ -37647,7 +37647,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 15, +@@ -37685,7 +37685,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 15, +@@ -37723,7 +37723,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": true, + "emitLight": 0, + "filterLight": 0, +@@ -39352,7 +39352,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 15, +@@ -39379,7 +39379,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 15, +@@ -39406,7 +39406,7 @@ + "resistance": 6.0, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 15, +@@ -39653,7 +39653,7 @@ + "resistance": 3.5, + "stackSize": 64, + "diggable": true, +- "material": "incorrect_for_wooden_tool", ++ "material": "mineable/pickaxe", + "transparent": false, + "emitLight": 0, + "filterLight": 15, From d5cfae27c95bf38c8fc0b81054eac4d9f51161ea Mon Sep 17 00:00:00 2001 From: MaxRobinsonTheGreat Date: Wed, 16 Apr 2025 12:30:26 -0500 Subject: [PATCH 13/13] add openrouter vision, gpt strict format --- src/models/gpt.js | 3 +-- src/models/openrouter.js | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/models/gpt.js b/src/models/gpt.js index 8540778..4f33f22 100644 --- a/src/models/gpt.js +++ b/src/models/gpt.js @@ -21,7 +21,7 @@ export class GPT { async sendRequest(turns, systemMessage, stop_seq='***') { let messages = [{'role': 'system', 'content': systemMessage}].concat(turns); - + messages = strictFormat(messages); const pack = { model: this.model_name || "gpt-3.5-turbo", messages, @@ -29,7 +29,6 @@ export class GPT { ...(this.params || {}) }; if (this.model_name.includes('o1')) { - pack.messages = strictFormat(messages); delete pack.stop; } diff --git a/src/models/openrouter.js b/src/models/openrouter.js index 8e4530a..5cbc090 100644 --- a/src/models/openrouter.js +++ b/src/models/openrouter.js @@ -52,6 +52,24 @@ export class OpenRouter { return res; } + async sendVisionRequest(messages, systemMessage, imageBuffer) { + const imageMessages = [...messages]; + imageMessages.push({ + role: "user", + content: [ + { type: "text", text: systemMessage }, + { + type: "image_url", + image_url: { + url: `data:image/jpeg;base64,${imageBuffer.toString('base64')}` + } + } + ] + }); + + return this.sendRequest(imageMessages, systemMessage); + } + async embed(text) { throw new Error('Embeddings are not supported by Openrouter.'); }