diff --git a/services/minecraft/src/agents/openai.ts b/services/minecraft/src/agents/openai.ts index ee7638c7f..f49ff41e3 100644 --- a/services/minecraft/src/agents/openai.ts +++ b/services/minecraft/src/agents/openai.ts @@ -44,7 +44,10 @@ export async function initActionAgent(ctx: BotContext): Promise { actionAgent = actionAgent.tool( action.name, action.schema, - action.perform(createSkillContext(ctx)), + async ({ parameters }) => { + logger.withFields({ name: action.name, parameters }).log('Calling action') + return action.perform(createSkillContext(ctx))(...Object.values(parameters)) + }, { description: action.description }, ) }) diff --git a/services/minecraft/src/components/aichat.ts b/services/minecraft/src/components/aichat.ts index a52f20d18..421dc6cce 100644 --- a/services/minecraft/src/components/aichat.ts +++ b/services/minecraft/src/components/aichat.ts @@ -1,25 +1,22 @@ -import type { messages } from 'neuri/openai' import type { BotContext, ComponentLifecycle } from 'src/composables/bot' import { useLogg } from '@guiiai/logg' -import { assistant, system, user } from 'neuri/openai' +import { messages, system, user } from 'neuri/openai' import { getAgent } from 'src/agents/openai' import { formBotChat } from 'src/middlewares/chat' -import { genSystemBasicPrompt } from 'src/prompts/agent' +import { genActionAgentPrompt } from 'src/prompts/agent' export function createAiChatComponent(ctx: BotContext): ComponentLifecycle { const logger = useLogg('aichat').useGlobalConfig() logger.log('Loading aichat plugin') - const history: ReturnType = [] - history.push(system(genSystemBasicPrompt('airi'))) - const onChat = formBotChat(ctx, async (username, message) => { logger.withFields({ username, message }).log('Chat message received') - history.push(user(message)) - const agent = getAgent() - const content = await agent.handle(history.concat(user(message)), async (c) => { + const content = await agent.handle(messages( + system(genActionAgentPrompt(ctx)), + user(`${username}: ${message}`), + ), async (c) => { logger.log('Generate response') try { @@ -28,10 +25,6 @@ export function createAiChatComponent(ctx: BotContext): ComponentLifecycle { logger.withFields({ completion }).log('Completion') const content = await completion?.firstContent() - if (content) { - history.push(assistant(content)) - } - return content } catch (e) { diff --git a/services/minecraft/src/main.ts b/services/minecraft/src/main.ts index 2111cb9f7..909bc1249 100644 --- a/services/minecraft/src/main.ts +++ b/services/minecraft/src/main.ts @@ -35,7 +35,7 @@ async function main() { const ticker = createTicker() ticker.on('tick', async ({ delta }) => { - logger.log(`Tick ${delta}ms`) + // logger.log(`Tick ${delta}ms`) }) process.on('SIGINT', () => { diff --git a/services/minecraft/src/skills/movement.ts b/services/minecraft/src/skills/movement.ts index 88a5846c5..cfc0227eb 100644 --- a/services/minecraft/src/skills/movement.ts +++ b/services/minecraft/src/skills/movement.ts @@ -1,8 +1,11 @@ import type { Entity } from 'prismarine-entity' import type { SkillContext } from './base' +import pathfinderModel from 'mineflayer-pathfinder' import * as world from '../composables/world' import { log } from './base' +const { goals, Movements } = pathfinderModel + /** * Navigate to a specific position */ @@ -25,7 +28,7 @@ export async function goToPosition( return true } - await bot.pathfinder.goto(bot.pathfinder.goals.GoalNear(x, y, z, minDistance)) + await bot.pathfinder.goto(new goals.GoalNear(x, y, z, minDistance)) log(ctx, `You have reached ${x}, ${y}, ${z}.`) return true } @@ -45,7 +48,8 @@ export async function goToNearestBlock( range = MAX_RANGE } - const block = world.getNearestBlock(ctx.bot, blockType, range) + const worldCtx = world.createWorldContext(ctx.botCtx) + const block = world.getNearestBlock(worldCtx, blockType, range) if (!block) { log(ctx, `Could not find any ${blockType} in ${range} blocks.`) return false @@ -66,8 +70,9 @@ export async function goToNearestEntity( range = 64, ): Promise { const { bot } = ctx + const worldCtx = world.createWorldContext(ctx.botCtx) const entity = world.getNearestEntityWhere( - bot, + worldCtx, entity => entity.name === entityType, range, ) @@ -110,7 +115,7 @@ export async function goToPlayer( return false } - await bot.pathfinder.goto(bot.pathfinder.goals.GoalFollow(player, distance), true) + await bot.pathfinder.goto(new goals.GoalFollow(player, distance)) log(ctx, `You have reached ${username}.`) return true } @@ -128,7 +133,7 @@ export async function followPlayer( if (!player) return false - bot.pathfinder.setGoal(bot.pathfinder.goals.GoalFollow(player, distance), true) + bot.pathfinder.setGoal(new goals.GoalFollow(player, distance)) log(ctx, `You are now actively following player ${username}.`) while (!ctx.shouldInterrupt) { @@ -136,7 +141,7 @@ export async function followPlayer( if (ctx.allowCheats && bot.entity.position.distanceTo(player.position) > 100 - && player.isOnGround) { + && player.onGround) { await goToPlayer(ctx, username) } } @@ -149,11 +154,11 @@ export async function followPlayer( export async function moveAway(ctx: SkillContext, distance: number): Promise { const { bot } = ctx const pos = bot.entity.position - const goal = bot.pathfinder.goals.GoalNear(pos.x, pos.y, pos.z, distance) - const invertedGoal = bot.pathfinder.goals.GoalInvert(goal) + const goal = new goals.GoalNear(pos.x, pos.y, pos.z, distance) + const invertedGoal = new goals.GoalInvert(goal) if (ctx.allowCheats) { - const move = new bot.pathfinder.Movements(bot) + const move = new Movements(bot) const path = await bot.pathfinder.getPathTo(move, invertedGoal, 10000) const lastMove = path.path[path.path.length - 1] @@ -181,8 +186,8 @@ export async function moveAwayFromEntity( distance = 16, ): Promise { const { bot } = ctx - const goal = bot.pathfinder.goals.GoalFollow(entity, distance) - const invertedGoal = bot.pathfinder.goals.GoalInvert(goal) + const goal = new goals.GoalFollow(entity, distance) + const invertedGoal = new goals.GoalInvert(goal) await bot.pathfinder.goto(invertedGoal) return true } @@ -192,7 +197,9 @@ export async function moveAwayFromEntity( */ export async function stay(ctx: SkillContext, seconds = 30): Promise { const start = Date.now() - while (!ctx.shouldInterrupt && (seconds === -1 || Date.now() - start < seconds * 1000)) { + const targetTime = seconds === -1 ? Infinity : start + seconds * 1000 + + while (!ctx.shouldInterrupt && Date.now() < targetTime) { await new Promise(resolve => setTimeout(resolve, 500)) }