diff --git a/services/minecraft/src/agents/action/tools.ts b/services/minecraft/src/agents/action/tools.ts index fb7592361..f7ad41b00 100644 --- a/services/minecraft/src/agents/action/tools.ts +++ b/services/minecraft/src/agents/action/tools.ts @@ -254,8 +254,11 @@ export const actionsList: Action[] = [ num: z.number().int().describe('The number of blocks to collect.').min(1), }), perform: mineflayer => async (type: string, num: number) => { - await collectBlock(mineflayer, type, num) - return `Collected [${type}] x${num}` + const collected = await collectBlock(mineflayer, type, num) + if (collected <= 0) { + throw new ActionError('RESOURCE_MISSING', `Failed to collect any ${type}`, { type, requested: num, collected }) + } + return `Collected [${type}] x${collected}` }, }, { diff --git a/services/minecraft/src/cognitive/conscious/brain.ts b/services/minecraft/src/cognitive/conscious/brain.ts index 6408a2998..98c3732e2 100644 --- a/services/minecraft/src/cognitive/conscious/brain.ts +++ b/services/minecraft/src/cognitive/conscious/brain.ts @@ -185,8 +185,11 @@ export class Brain { return `Perception [${signal.type}]${sourceInfo}: ${signal.description}` } case 'feedback': { - const { status, result, error } = event.payload - return `Internal Feedback: ${status}. Result: ${JSON.stringify(result || error)}` + const { status, action, result, error } = event.payload + const actionCtx = action + ? { type: action.type, ...(action.type === 'physical' ? { tool: action.step.tool, params: action.step.params } : { message: action.message }) } + : undefined + return `Internal Feedback: ${status}. Last Action: ${JSON.stringify(actionCtx)}. Result: ${JSON.stringify(result || error)}` } default: return '' diff --git a/services/minecraft/src/skills/actions/collect-block.ts b/services/minecraft/src/skills/actions/collect-block.ts index 8a764f62f..72e65481f 100644 --- a/services/minecraft/src/skills/actions/collect-block.ts +++ b/services/minecraft/src/skills/actions/collect-block.ts @@ -4,6 +4,7 @@ import type { Mineflayer } from '../../libs/mineflayer' import pathfinder from 'mineflayer-pathfinder' +import { ActionError } from '../../utils/errors' import { useLogger } from '../../utils/logger' import { breakBlockAt } from '../blocks' import { getNearestBlocks } from '../world' @@ -21,10 +22,10 @@ export async function collectBlock( blockType: string, num = 1, range = 16, -): Promise { +): Promise { if (num < 1) { logger.log(`Invalid number of blocks to collect: ${num}.`) - return false + return 0 } const blockTypes = [blockType] @@ -112,12 +113,17 @@ export async function collectBlock( break } + if (err instanceof ActionError && (err.code === 'CRAFTING_FAILED' || err.code === 'RESOURCE_MISSING')) { + // Don't get stuck in retry loop + throw err + } + continue } } logger.log(`Collected ${collected} ${blockType}(s).`) - return collected > 0 + return collected } // Helper function to mine a block and collect drops diff --git a/services/minecraft/src/skills/actions/ensure.ts b/services/minecraft/src/skills/actions/ensure.ts index 19901e73c..88f4c6e66 100644 --- a/services/minecraft/src/skills/actions/ensure.ts +++ b/services/minecraft/src/skills/actions/ensure.ts @@ -295,13 +295,13 @@ export async function ensureCobblestone(mineflayer: Mineflayer, requiredCobblest const cobblestoneShortage = requiredCobblestone - cobblestoneCount try { - const success = await collectBlock( + const collected = await collectBlock( mineflayer, 'stone', cobblestoneShortage, maxDistance, ) - if (!success) { + if (collected <= 0) { await moveAway(mineflayer, 10) continue } @@ -337,7 +337,10 @@ export async function ensureCoal(mineflayer: Mineflayer, neededAmount: number, m const coalShortage = neededAmount - coalCount try { - await collectBlock(mineflayer, 'coal_ore', coalShortage, maxDistance) + const collected = await collectBlock(mineflayer, 'coal_ore', coalShortage, maxDistance) + if (collected <= 0) { + continue + } } catch (err: unknown) { if (err instanceof Error && err.message.includes('right tools')) {