fix: useSkillContext
This commit is contained in:
@@ -1,9 +1,9 @@
|
|||||||
import { messages, system, user } from 'neuri/openai'
|
import { messages, system, user } from 'neuri/openai'
|
||||||
import { sleep } from 'src/utils/helper'
|
|
||||||
import { beforeAll, describe, expect, it } from 'vitest'
|
import { beforeAll, describe, expect, it } from 'vitest'
|
||||||
import { createBot, useBot } from '../composables/bot'
|
import { createBot, useBot } from '../composables/bot'
|
||||||
import { botConfig, initEnv } from '../composables/config'
|
import { botConfig, initEnv } from '../composables/config'
|
||||||
import { genActionAgentPrompt, genQueryAgentPrompt } from '../prompts/agent'
|
import { genActionAgentPrompt, genQueryAgentPrompt } from '../prompts/agent'
|
||||||
|
import { sleep } from '../utils/helper'
|
||||||
import { initLogger } from '../utils/logger'
|
import { initLogger } from '../utils/logger'
|
||||||
import { initAgent } from './openai'
|
import { initAgent } from './openai'
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import * as skills from '../skills'
|
|||||||
|
|
||||||
type ActionResult = string | Promise<string>
|
type ActionResult = string | Promise<string>
|
||||||
|
|
||||||
interface Action {
|
export interface Action {
|
||||||
readonly name: string
|
readonly name: string
|
||||||
readonly description: string
|
readonly description: string
|
||||||
readonly schema: z.ZodObject<any>
|
readonly schema: z.ZodObject<any>
|
||||||
@@ -105,23 +105,22 @@ export const actionsList: Action[] = [
|
|||||||
// }
|
// }
|
||||||
// },
|
// },
|
||||||
|
|
||||||
// getStopAction(): Action {
|
{
|
||||||
// return {
|
name: 'stop',
|
||||||
// name: 'stop',
|
description: 'Force stop all actions and commands that are currently executing.',
|
||||||
// description: 'Force stop all actions and commands that are currently executing.',
|
schema: z.object({}),
|
||||||
// schema: z.object({}),
|
perform: (ctx: SkillContext) => async () => {
|
||||||
// perform: (ctx: BotContext) => async () => {
|
// await ctx.actions.stop()
|
||||||
// await ctx.actions.stop()
|
// ctx.clearBotLogs()
|
||||||
// ctx.clearBotLogs()
|
// ctx.actions.cancelResume()
|
||||||
// ctx.actions.cancelResume()
|
// ctx.bot.emit('idle')
|
||||||
// ctx.bot.emit('idle')
|
ctx.shouldInterrupt = true
|
||||||
// let msg = 'Agent stopped.'
|
const msg = 'Agent stopped.'
|
||||||
// if (ctx.self_prompter.on)
|
// if (ctx.self_prompter.on)
|
||||||
// msg += ' Self-prompting still active.'
|
// msg += ' Self-prompting still active.'
|
||||||
// return msg
|
return msg
|
||||||
// },
|
},
|
||||||
// }
|
},
|
||||||
// },
|
|
||||||
|
|
||||||
// getStfuAction(): Action {
|
// getStfuAction(): Action {
|
||||||
// return {
|
// return {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import type { BotContext } from '../composables/bot'
|
|||||||
import { useLogg } from '@guiiai/logg'
|
import { useLogg } from '@guiiai/logg'
|
||||||
import { agent, neuri } from 'neuri'
|
import { agent, neuri } from 'neuri'
|
||||||
import { openaiConfig } from '../composables/config'
|
import { openaiConfig } from '../composables/config'
|
||||||
import { createSkillContext } from '../skills'
|
import { useSkillContext } from '../skills'
|
||||||
import { actionsList } from './actions'
|
import { actionsList } from './actions'
|
||||||
|
|
||||||
let neuriAgent: Neuri | undefined
|
let neuriAgent: Neuri | undefined
|
||||||
@@ -47,7 +47,7 @@ export async function initActionAgent(ctx: BotContext): Promise<Agent> {
|
|||||||
async ({ parameters }) => {
|
async ({ parameters }) => {
|
||||||
logger.withFields({ name: action.name, parameters }).log('Calling action')
|
logger.withFields({ name: action.name, parameters }).log('Calling action')
|
||||||
ctx.memory.actions.push(action)
|
ctx.memory.actions.push(action)
|
||||||
return action.perform(createSkillContext(ctx))(...Object.values(parameters))
|
return action.perform(useSkillContext(ctx))(...Object.values(parameters))
|
||||||
},
|
},
|
||||||
{ description: action.description },
|
{ description: action.description },
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ export function createAiChatComponent(ctx: BotContext): ComponentLifecycle {
|
|||||||
|
|
||||||
ctx.memory.chatHistory.push(system(genActionAgentPrompt(ctx)))
|
ctx.memory.chatHistory.push(system(genActionAgentPrompt(ctx)))
|
||||||
|
|
||||||
|
// todo: get system message
|
||||||
const onChat = formBotChat(ctx, async (username, message) => {
|
const onChat = formBotChat(ctx, async (username, message) => {
|
||||||
logger.withFields({ username, message }).log('Chat message received')
|
logger.withFields({ username, message }).log('Chat message received')
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import type { Message } from 'neuri/openai'
|
import type { Message } from 'neuri/openai'
|
||||||
import type { Action } from 'src/agents/actions'
|
import type { Action } from '../agents/actions'
|
||||||
import type { BotInternalEventHandlers, BotInternalEvents } from './events'
|
import type { BotInternalEventHandlers, BotInternalEvents } from './events'
|
||||||
import { useLogg } from '@guiiai/logg'
|
import { useLogg } from '@guiiai/logg'
|
||||||
import mineflayer, { type Bot, type BotOptions } from 'mineflayer'
|
import mineflayer, { type Bot, type BotOptions } from 'mineflayer'
|
||||||
@@ -51,6 +51,7 @@ export interface ComponentLifecycle {
|
|||||||
cleanup: () => void
|
cleanup: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// todo: reconnect
|
||||||
export function createBot(options: BotOptions): Bot {
|
export function createBot(options: BotOptions): Bot {
|
||||||
logger.withFields({ options }).log('Creating bot')
|
logger.withFields({ options }).log('Creating bot')
|
||||||
ctx = {
|
ctx = {
|
||||||
@@ -68,6 +69,7 @@ export function createBot(options: BotOptions): Bot {
|
|||||||
},
|
},
|
||||||
memory: {
|
memory: {
|
||||||
chatHistory: [],
|
chatHistory: [],
|
||||||
|
actions: [],
|
||||||
},
|
},
|
||||||
status: new Map(),
|
status: new Map(),
|
||||||
health: {
|
health: {
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import { createTicker } from './utils/ticker'
|
|||||||
const logger = useLogg('main').useGlobalConfig()
|
const logger = useLogg('main').useGlobalConfig()
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
initLogger()
|
initLogger() // todo: save logs to file
|
||||||
initEnv()
|
initEnv()
|
||||||
|
|
||||||
createBot(botConfig)
|
createBot(botConfig)
|
||||||
|
|||||||
@@ -1,5 +1,19 @@
|
|||||||
import type { Bot } from 'mineflayer'
|
import type { Bot } from 'mineflayer'
|
||||||
import type { BotContext } from 'src/composables/bot'
|
import type { BotContext } from '../composables/bot'
|
||||||
|
import { useLogg } from '@guiiai/logg'
|
||||||
|
|
||||||
|
let ctx: SkillContext | undefined
|
||||||
|
const logger = useLogg('skills').useGlobalConfig()
|
||||||
|
|
||||||
|
export function useSkillContext(botCtx: BotContext): SkillContext {
|
||||||
|
if (!ctx) {
|
||||||
|
logger.log('Creating skill context')
|
||||||
|
ctx = createSkillContext(botCtx)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ctx
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Context for skill execution
|
* Context for skill execution
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -110,41 +110,69 @@ export async function followPlayer(
|
|||||||
username: string,
|
username: string,
|
||||||
distance = 4,
|
distance = 4,
|
||||||
): Promise<boolean> {
|
): Promise<boolean> {
|
||||||
|
// const player = ctx.bot.players[username]?.entity
|
||||||
|
// if (!player) {
|
||||||
|
// log(ctx, `Could not find player ${username}`)
|
||||||
|
// return false
|
||||||
|
// }
|
||||||
|
|
||||||
|
// const movements = new Movements(ctx.bot)
|
||||||
|
// ctx.bot.pathfinder.setMovements(movements)
|
||||||
|
// ctx.bot.pathfinder.setGoal(new goals.GoalNear(player.position.x, player.position.y, player.position.z, distance))
|
||||||
|
|
||||||
|
// log(ctx, `Started following ${username}`)
|
||||||
|
|
||||||
|
// const followInterval = setInterval(() => {
|
||||||
|
// const target = ctx.bot.players[username]?.entity
|
||||||
|
// if (!target) {
|
||||||
|
// log(ctx, 'Lost sight of player')
|
||||||
|
// clearInterval(followInterval)
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
|
||||||
|
// const { x, y, z } = target.position
|
||||||
|
// ctx.bot.pathfinder.setGoal(new goals.GoalNear(x, y, z, distance))
|
||||||
|
// }, 1000)
|
||||||
|
|
||||||
|
// while (!ctx.shouldInterrupt) {
|
||||||
|
// await new Promise(resolve => setTimeout(resolve, 500))
|
||||||
|
|
||||||
|
// if (ctx.allowCheats && ctx.bot.entity.position.distanceTo(player.position) > 100) {
|
||||||
|
// await goToPlayer(ctx, username)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // TODO: need global status management
|
||||||
|
// clearInterval(followInterval)
|
||||||
|
// ctx.bot.pathfinder.stop()
|
||||||
|
// return true
|
||||||
|
|
||||||
const player = ctx.bot.players[username]?.entity
|
const player = ctx.bot.players[username]?.entity
|
||||||
if (!player) {
|
if (!player) {
|
||||||
log(ctx, `Could not find player ${username}`)
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
const movements = new Movements(ctx.bot)
|
const movements = new Movements(ctx.bot)
|
||||||
ctx.bot.pathfinder.setMovements(movements)
|
ctx.bot.pathfinder.setMovements(movements)
|
||||||
ctx.bot.pathfinder.setGoal(new goals.GoalNear(player.position.x, player.position.y, player.position.z, distance))
|
ctx.bot.pathfinder.setGoal(new goals.GoalFollow(player, distance), true)
|
||||||
|
log(ctx, `You are now actively following player ${username}.`)
|
||||||
log(ctx, `Started following ${username}`)
|
|
||||||
|
|
||||||
const followInterval = setInterval(() => {
|
|
||||||
const target = ctx.bot.players[username]?.entity
|
|
||||||
if (!target) {
|
|
||||||
log(ctx, 'Lost sight of player')
|
|
||||||
clearInterval(followInterval)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const { x, y, z } = target.position
|
|
||||||
ctx.bot.pathfinder.setGoal(new goals.GoalNear(x, y, z, distance))
|
|
||||||
}, 1000)
|
|
||||||
|
|
||||||
while (!ctx.shouldInterrupt) {
|
while (!ctx.shouldInterrupt) {
|
||||||
await new Promise(resolve => setTimeout(resolve, 500))
|
await new Promise(resolve => setTimeout(resolve, 500))
|
||||||
|
|
||||||
if (ctx.allowCheats && ctx.bot.entity.position.distanceTo(player.position) > 100) {
|
if (ctx.allowCheats && ctx.bot.entity.position.distanceTo(player.position) > 100 && player.onGround) {
|
||||||
await goToPlayer(ctx, username)
|
await goToPlayer(ctx, username)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: need global status management
|
// if (ctx.bot.modes?.isOn('unstuck')) {
|
||||||
// clearInterval(followInterval)
|
// const isNearby = ctx.bot.entity.position.distanceTo(player.position) <= distance + 1
|
||||||
// ctx.bot.pathfinder.stop()
|
// if (isNearby) {
|
||||||
|
// ctx.bot.modes.pause('unstuck')
|
||||||
|
// } else {
|
||||||
|
// ctx.bot.modes.unpause('unstuck')
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -184,7 +212,6 @@ export async function moveAwayFromEntity(
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export async function stay(ctx: SkillContext, seconds = 30): Promise<boolean> {
|
export async function stay(ctx: SkillContext, seconds = 30): Promise<boolean> {
|
||||||
const start = Date.now()
|
const start = Date.now()
|
||||||
const targetTime = seconds === -1 ? Infinity : start + seconds * 1000
|
const targetTime = seconds === -1 ? Infinity : start + seconds * 1000
|
||||||
|
|||||||
Reference in New Issue
Block a user