refactor(minecraft): code cleanup, better naming
This commit is contained in:
@@ -80,7 +80,7 @@ export class ChatAgentImpl extends AbstractAgent implements ChatAgent {
|
||||
this.logger.withField('message', message).log('Sending message')
|
||||
|
||||
// We also record our own messages in history (handled by on('chat') listener usually?
|
||||
// No, on('chat') filters out bot's own messages in LLMAgent plugin usually to avoid loops.
|
||||
// No, on('chat') filters out bot's own messages in CognitiveEngine plugin usually to avoid loops.
|
||||
// So we manually add to history?
|
||||
// Wait, the orchestrator call bot.chat() before. Did it record it?
|
||||
// In processMessage, we added generated response to history.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Vec3 } from 'vec3'
|
||||
import type { Vec3 } from 'vec3'
|
||||
|
||||
export interface SelfState {
|
||||
status: 'idle' | 'moving' | 'working' | 'chatting' | 'busy'
|
||||
@@ -12,17 +12,17 @@ export interface SelfState {
|
||||
export interface EnvironmentState {
|
||||
time: string // 'day' | 'night' | 'sunset' | 'sunrise'
|
||||
weather: 'clear' | 'rain' | 'thunder'
|
||||
nearbyPlayers: string[]
|
||||
nearbyAgents: string[]
|
||||
nearbyEntities: string[] // significant entities (mobs, dropped items of interest)
|
||||
lightLevel: number
|
||||
}
|
||||
|
||||
export interface BlackboardState {
|
||||
currentGoal: string
|
||||
currentThought: string
|
||||
executionStrategy: string
|
||||
self: SelfState
|
||||
environment: EnvironmentState
|
||||
currentGoal: string
|
||||
currentThought: string
|
||||
executionStrategy: string
|
||||
self: SelfState
|
||||
environment: EnvironmentState
|
||||
}
|
||||
|
||||
export class Blackboard {
|
||||
@@ -44,7 +44,7 @@ export class Blackboard {
|
||||
environment: {
|
||||
time: 'day',
|
||||
weather: 'clear',
|
||||
nearbyPlayers: [],
|
||||
nearbyAgents: [],
|
||||
nearbyEntities: [],
|
||||
lightLevel: 15,
|
||||
},
|
||||
@@ -60,24 +60,24 @@ export class Blackboard {
|
||||
|
||||
// Setters (Partial updates allowed)
|
||||
public update(updates: Partial<BlackboardState>): void {
|
||||
this._state = { ...this._state, ...updates }
|
||||
this._state = { ...this._state, ...updates }
|
||||
}
|
||||
|
||||
public updateSelf(updates: Partial<SelfState>): void {
|
||||
this._state.self = { ...this._state.self, ...updates }
|
||||
this._state.self = { ...this._state.self, ...updates }
|
||||
}
|
||||
|
||||
public updateEnvironment(updates: Partial<EnvironmentState>): void {
|
||||
this._state.environment = { ...this._state.environment, ...updates }
|
||||
this._state.environment = { ...this._state.environment, ...updates }
|
||||
}
|
||||
|
||||
public getSnapshot(): BlackboardState {
|
||||
// Return a deep copy or safe reference?
|
||||
// For now, return a shallow copy of the state structure
|
||||
return {
|
||||
...this._state,
|
||||
self: { ...this._state.self }, // location (Vec3) is an object, but usually treated efficiently.
|
||||
environment: { ...this._state.environment, nearbyPlayers: [...this._state.environment.nearbyPlayers], nearbyEntities: [...this._state.environment.nearbyEntities] }
|
||||
}
|
||||
// Return a deep copy or safe reference?
|
||||
// For now, return a shallow copy of the state structure
|
||||
return {
|
||||
...this._state,
|
||||
self: { ...this._state.self }, // location (Vec3) is an object, but usually treated efficiently.
|
||||
environment: { ...this._state.environment, nearbyAgents: [...this._state.environment.nearbyAgents], nearbyEntities: [...this._state.environment.nearbyEntities] },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import type { Neuri } from 'neuri'
|
||||
import type { TaskExecutor } from '../action/task-executor'
|
||||
import type { ActionInstruction } from '../action/types'
|
||||
import type { EventManager } from '../perception/event-manager'
|
||||
import type { MineflayerWithAgents, UserIntentPayload } from '../types'
|
||||
import type { MineflayerWithAgents, StimulusPayload } from '../types'
|
||||
|
||||
import { system, user } from 'neuri/openai'
|
||||
|
||||
@@ -38,10 +38,10 @@ export class Brain {
|
||||
public init(bot: MineflayerWithAgents): void {
|
||||
this.deps.logger.log('Brain: Initializing...')
|
||||
|
||||
// Listen to User Intents (Chat/Voice)
|
||||
// Listen to Stimuli (Chat/Voice)
|
||||
// We treat these as "Sensory Inputs" that trigger the Cognitive Cycle
|
||||
this.deps.eventManager.on<UserIntentPayload>('user_intent', async (event) => {
|
||||
this.deps.logger.log(`Brain: Received intent from ${event.source.id}: ${event.payload.content}`)
|
||||
this.deps.eventManager.on<StimulusPayload>('stimulus', async (event) => {
|
||||
this.deps.logger.log(`Brain: Received stimulus from ${event.source.id}: ${event.payload.content}`)
|
||||
await this.processEvent(bot, event)
|
||||
})
|
||||
|
||||
@@ -49,7 +49,7 @@ export class Brain {
|
||||
this.deps.taskExecutor.on('action:completed', async ({ action, result }) => {
|
||||
this.deps.logger.log(`Brain: Action completed: ${action.type}`)
|
||||
await this.processEvent(bot, {
|
||||
type: 'action:feedback',
|
||||
type: 'feedback',
|
||||
payload: {
|
||||
status: 'success',
|
||||
action,
|
||||
@@ -63,7 +63,7 @@ export class Brain {
|
||||
this.deps.taskExecutor.on('action:failed', async ({ action, error }) => {
|
||||
this.deps.logger.withError(error).warn(`Brain: Action failed: ${action.type}`)
|
||||
await this.processEvent(bot, {
|
||||
type: 'action:feedback',
|
||||
type: 'feedback',
|
||||
payload: {
|
||||
status: 'failure',
|
||||
action,
|
||||
@@ -85,13 +85,13 @@ export class Brain {
|
||||
|
||||
// 2. Orient (Contextualize Event)
|
||||
let contextMsg = ''
|
||||
if (event.type === 'user_intent') {
|
||||
contextMsg = `User ${event.source.id} says: "${event.payload.content}"`
|
||||
if (event.type === 'stimulus') {
|
||||
contextMsg = `${event.source.type} stimulus from ${event.source.id}: "${event.payload.content}"`
|
||||
}
|
||||
else if (event.type === 'action:feedback') {
|
||||
else if (event.type === 'feedback') {
|
||||
const { status, result, error, action } = event.payload
|
||||
const actionDesc = action.type === 'physical' ? action.step.tool : 'chat'
|
||||
contextMsg = `Action Feedback: ${actionDesc} ${status}. Result: ${JSON.stringify(result || error)}`
|
||||
contextMsg = `Internal Feedback: ${actionDesc} ${status}. Result: ${JSON.stringify(result || error)}`
|
||||
}
|
||||
|
||||
// 3. Decide (LLM Call)
|
||||
@@ -130,7 +130,7 @@ export class Brain {
|
||||
this.blackboard.updateEnvironment({
|
||||
time: bot.bot.time.isDay ? 'day' : 'night',
|
||||
weather: bot.bot.isRaining ? 'rain' : 'clear',
|
||||
nearbyPlayers: Object.keys(bot.bot.players).filter(p => p !== bot.bot.username),
|
||||
nearbyAgents: Object.keys(bot.bot.players).filter(p => p !== bot.bot.username),
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -1,269 +0,0 @@
|
||||
import type { Logg } from '@guiiai/logg'
|
||||
import type { Neuri, NeuriContext } from 'neuri'
|
||||
|
||||
import type { TaskExecutor } from '../action/task-executor'
|
||||
import type { EventManager } from '../perception/event-manager'
|
||||
import type { BotEvent, MineflayerWithAgents, UserIntentPayload } from '../types'
|
||||
import type { CancellationToken } from './task-state'
|
||||
|
||||
import { withRetry } from '@moeru/std'
|
||||
import { system, user } from 'neuri/openai'
|
||||
|
||||
import { DebugServer } from '../../debug-server'
|
||||
import { ActionError } from '../../utils/errors'
|
||||
import { handleLLMCompletion } from './completion'
|
||||
import { generateStatusPrompt } from './prompt'
|
||||
import { TaskManager } from './task-manager'
|
||||
|
||||
export class Orchestrator {
|
||||
private taskManager: TaskManager
|
||||
|
||||
// We no longer need an event queue for blocking purposes,
|
||||
// but we might keep it if we want to handle explicit queuing later.
|
||||
// For now, removing the blocking logic.
|
||||
|
||||
constructor(
|
||||
private readonly deps: {
|
||||
eventManager: EventManager
|
||||
neuri: Neuri
|
||||
logger: Logg
|
||||
taskExecutor: TaskExecutor
|
||||
},
|
||||
) {
|
||||
this.taskManager = new TaskManager(deps.logger)
|
||||
}
|
||||
|
||||
public init(bot: MineflayerWithAgents): void {
|
||||
this.deps.eventManager.on<UserIntentPayload>('user_intent', async (event) => {
|
||||
// Don't await here to allow event loop to continue?
|
||||
// Actually, if we await, the next event won't process until this one finishes
|
||||
// ONLY IF eventManager awaits listeners.
|
||||
// Assuming we want true parallelism, we should probably not await the full task execution,
|
||||
// but we should await the initial decision making.
|
||||
// However, handleUserIntent is async void, so awaiting it in event emitter is standard.
|
||||
// To ensure non-blocking, handleUserIntent should return quickly.
|
||||
|
||||
// Let's await it, but ensure handleUserIntent doesn't block on long operations
|
||||
// before deciding if it's a new task.
|
||||
await this.handleUserIntent(bot, event)
|
||||
})
|
||||
}
|
||||
|
||||
private async handleUserIntent(bot: MineflayerWithAgents, event: BotEvent<UserIntentPayload>): Promise<void> {
|
||||
const { payload, source } = event
|
||||
const { content, metadata } = payload
|
||||
const username = metadata?.displayName || source.id
|
||||
|
||||
// Layered Architecture: Check for inhibition from Reflex layer
|
||||
if (event.handled) {
|
||||
this.deps.logger.log('Orchestrator: Intent already handled by Reflex layer, inhibiting Conscious processing')
|
||||
return
|
||||
}
|
||||
|
||||
// High priority interruption check
|
||||
if (this.shouldCancelPrimaryTask(event)) {
|
||||
this.deps.logger
|
||||
.withFields({
|
||||
currentPrimaryId: this.taskManager.getPrimaryTask()?.id,
|
||||
priority: event.priority,
|
||||
})
|
||||
.log('Orchestrator: Cancelling primary task for high-priority event')
|
||||
|
||||
this.taskManager.cancelPrimaryTask('High-priority event received')
|
||||
// Note: We continue to process this event as a new task
|
||||
}
|
||||
|
||||
// Create new task (Secondary by default if primary exists, Primary if none exists)
|
||||
const task = this.taskManager.createTask(content)
|
||||
this.deps.logger
|
||||
.withFields({ username, content, taskId: task.id })
|
||||
.log('Orchestrator: Starting new task processing')
|
||||
this.broadcastTaskStatus()
|
||||
|
||||
try {
|
||||
// 1. Update memory
|
||||
bot.memory.chatHistory.push(user(`${username}: ${content}`))
|
||||
|
||||
// 2. Execute task with cancellation support
|
||||
// This will now handle conflicts internally
|
||||
this.executeTaskWithCancellation(bot, event, task).catch((err) => {
|
||||
this.deps.logger.withError(err).error('Orchestrator: Async task execution failed')
|
||||
})
|
||||
|
||||
// We return immediately to allow event loop to process next event
|
||||
// (Effectively making it fire-and-forget from the EventManager's perspective)
|
||||
}
|
||||
catch (error) {
|
||||
this.deps.logger.withError(error).warn('Orchestrator: Failed to initiate task')
|
||||
}
|
||||
}
|
||||
|
||||
private async executeTaskWithCancellation(
|
||||
bot: MineflayerWithAgents,
|
||||
event: BotEvent<UserIntentPayload>,
|
||||
task: { id: string, cancellationToken: CancellationToken }, // Use TaskContext type if imported
|
||||
): Promise<void> {
|
||||
const { payload, source } = event
|
||||
const { content } = payload
|
||||
const { cancellationToken, id: taskId } = task
|
||||
|
||||
try {
|
||||
// Planning phase
|
||||
if (cancellationToken.isCancelled)
|
||||
return
|
||||
this.taskManager.updateTaskStatus(taskId, 'planning')
|
||||
this.broadcastTaskStatus()
|
||||
this.deps.logger.log('Orchestrator: Starting planning phase')
|
||||
|
||||
const availableActions = this.deps.taskExecutor.getAvailableActions()
|
||||
const plan = await bot.planning.createPlan(content, availableActions)
|
||||
this.taskManager.setTaskPlan(taskId, plan)
|
||||
this.deps.logger.withFields({ steps: plan.steps.length }).log('Orchestrator: Plan created')
|
||||
|
||||
// CONFLICT RESOLUTION
|
||||
if (plan.requiresAction) {
|
||||
// If this task requires action, check if it conflicts with a primary task
|
||||
const primaryTask = this.taskManager.getPrimaryTask()
|
||||
|
||||
// If there is a primary task and IT IS NOT THIS TASK
|
||||
if (primaryTask && primaryTask.id !== taskId) {
|
||||
this.deps.logger.log('Orchestrator: Conflict detected - Secondary task requires action while Primary is busy')
|
||||
|
||||
// Conflict Policy: Reject secondary action tasks
|
||||
const busyMessage = `I'm currently busy with "${primaryTask.goal}". Please ask me to "${content}" later or tell me to stop.`
|
||||
if (source.reply)
|
||||
source.reply(busyMessage)
|
||||
else bot.bot.chat(busyMessage)
|
||||
|
||||
// Abort this secondary task
|
||||
this.taskManager.completeTask(taskId)
|
||||
this.broadcastTaskStatus()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Execution phase
|
||||
if (cancellationToken.isCancelled)
|
||||
return
|
||||
|
||||
if (plan.requiresAction) {
|
||||
this.taskManager.updateTaskStatus(taskId, 'executing')
|
||||
this.broadcastTaskStatus()
|
||||
this.deps.logger.log('Orchestrator: Executing plan')
|
||||
|
||||
// Retry loop implementation
|
||||
let currentPlan = plan
|
||||
let retryCount = 0
|
||||
const MAX_RETRIES = 3
|
||||
|
||||
while (retryCount < MAX_RETRIES) {
|
||||
if (cancellationToken.isCancelled)
|
||||
return
|
||||
|
||||
try {
|
||||
await this.deps.taskExecutor.executePlan(currentPlan, cancellationToken)
|
||||
this.deps.logger.log('Orchestrator: Plan executed successfully')
|
||||
break // Success
|
||||
}
|
||||
catch (error: any) {
|
||||
if (cancellationToken.isCancelled)
|
||||
return
|
||||
|
||||
// Check if it's an actionable error
|
||||
const isActionError = error instanceof ActionError
|
||||
if (!isActionError)
|
||||
throw error // Re-throw system errors
|
||||
|
||||
retryCount++
|
||||
if (retryCount >= MAX_RETRIES)
|
||||
throw error // Give up
|
||||
|
||||
this.deps.logger.withError(error).warn(`Orchestrator: Plan execution failed (Attempt ${retryCount}/${MAX_RETRIES}). Adjusting plan...`)
|
||||
|
||||
// Adjust plan
|
||||
const availableActions = this.deps.taskExecutor.getAvailableActions()
|
||||
currentPlan = await bot.planning.adjustPlan(
|
||||
currentPlan,
|
||||
error.message,
|
||||
'system',
|
||||
availableActions,
|
||||
)
|
||||
this.taskManager.setTaskPlan(taskId, currentPlan)
|
||||
this.broadcastTaskStatus()
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.deps.logger.log('Orchestrator: No physical actions required, skipping execution phase')
|
||||
}
|
||||
|
||||
// Response generation phase
|
||||
if (cancellationToken.isCancelled)
|
||||
return
|
||||
this.taskManager.updateTaskStatus(taskId, 'responding')
|
||||
this.broadcastTaskStatus()
|
||||
this.deps.logger.log('Orchestrator: Generating response')
|
||||
|
||||
const statusPrompt = await generateStatusPrompt(bot)
|
||||
const taskContext = this.taskManager.getTaskContextForLLM()
|
||||
|
||||
const response = await this.deps.neuri.handleStateless(
|
||||
[
|
||||
...bot.memory.chatHistory,
|
||||
system(statusPrompt),
|
||||
system(`Task Context:\n${taskContext}`), // Provide full context of all tasks
|
||||
],
|
||||
async (c: NeuriContext) => {
|
||||
this.deps.logger.log('Orchestrator: thinking...')
|
||||
return withRetry<NeuriContext, string>(
|
||||
ctx => handleLLMCompletion(ctx, bot, this.deps.logger),
|
||||
{
|
||||
retry: 3,
|
||||
retryDelay: 1000,
|
||||
},
|
||||
)(c)
|
||||
},
|
||||
)
|
||||
|
||||
// Reply
|
||||
if (cancellationToken.isCancelled)
|
||||
return
|
||||
if (response) {
|
||||
this.deps.logger.withFields({ response }).log('Orchestrator: Responded')
|
||||
if (source.reply) {
|
||||
source.reply(response)
|
||||
}
|
||||
else {
|
||||
bot.bot.chat(response)
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
this.deps.logger.withError(error).warn(`Orchestrator: Task ${taskId} processing failed`)
|
||||
// Optional: notify user of failure
|
||||
}
|
||||
finally {
|
||||
this.taskManager.completeTask(taskId)
|
||||
this.broadcastTaskStatus()
|
||||
}
|
||||
}
|
||||
|
||||
private shouldCancelPrimaryTask(event: BotEvent<UserIntentPayload>): boolean {
|
||||
const primaryTask = this.taskManager.getPrimaryTask()
|
||||
if (!primaryTask)
|
||||
return false
|
||||
|
||||
// High priority events should cancel current task
|
||||
const HIGH_PRIORITY_THRESHOLD = 8
|
||||
return (event.priority ?? 5) >= HIGH_PRIORITY_THRESHOLD
|
||||
}
|
||||
|
||||
private broadcastTaskStatus(): void {
|
||||
const debugServer = DebugServer.getInstance()
|
||||
debugServer.broadcast('task-status', {
|
||||
currentTask: this.taskManager.getPrimaryTask(), // For backward compatibility with UI
|
||||
activeTasks: this.taskManager.getAllActiveTasks(),
|
||||
history: this.taskManager.getTaskHistory(),
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -29,7 +29,7 @@ export function generateBrainSystemPrompt(
|
||||
思绪: "${blackboard.thought}"
|
||||
策略: "${blackboard.strategy}"
|
||||
自身: 位置${blackboard.self.location} 生命${blackboard.self.health} 饱食${blackboard.self.food}
|
||||
环境: ${blackboard.environment.time} ${blackboard.environment.weather} 玩家[${blackboard.environment.nearbyPlayers.join(',')}]
|
||||
环境: ${blackboard.environment.time} ${blackboard.environment.weather} 附近智体[${blackboard.environment.nearbyAgents.join(',')}]
|
||||
|
||||
可用动作:
|
||||
${availableActionsJson}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import type { MineflayerPlugin } from '../libs/mineflayer'
|
||||
import type { LLMAgentOptions, MineflayerWithAgents } from './types'
|
||||
import type { CognitiveEngineOptions, MineflayerWithAgents } from './types'
|
||||
|
||||
import { config } from '../composables/config'
|
||||
import { ChatMessageHandler } from '../libs/mineflayer'
|
||||
import { createAgentContainer } from './container'
|
||||
|
||||
export function LLMAgent(options: LLMAgentOptions): MineflayerPlugin {
|
||||
export function CognitiveEngine(options: CognitiveEngineOptions): MineflayerPlugin {
|
||||
let container: ReturnType<typeof createAgentContainer>
|
||||
|
||||
return {
|
||||
@@ -44,7 +44,7 @@ export function LLMAgent(options: LLMAgentOptions): MineflayerPlugin {
|
||||
return
|
||||
|
||||
eventManager.emit({
|
||||
type: 'user_intent',
|
||||
type: 'stimulus',
|
||||
payload: {
|
||||
content: message,
|
||||
metadata: {
|
||||
@@ -61,11 +61,11 @@ export function LLMAgent(options: LLMAgentOptions): MineflayerPlugin {
|
||||
|
||||
options.airiClient.onEvent('input:text:voice', (event) => {
|
||||
eventManager.emit({
|
||||
type: 'user_intent',
|
||||
type: 'stimulus',
|
||||
payload: {
|
||||
content: event.data.transcription,
|
||||
metadata: {
|
||||
displayName: (event.data.discord?.guildMember as any)?.nick || (event.data.discord?.guildMember as any)?.user?.username || 'Voice User',
|
||||
displayName: (event.data.discord?.guildMember as any)?.nick || (event.data.discord?.guildMember as any)?.user?.username || 'Voice Stimulus',
|
||||
},
|
||||
},
|
||||
source: {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { Logg } from '@guiiai/logg'
|
||||
|
||||
import type { EventManager } from '../perception/event-manager'
|
||||
import type { BotEvent, MineflayerWithAgents, UserIntentPayload } from '../types'
|
||||
import type { BotEvent, MineflayerWithAgents, StimulusPayload } from '../types'
|
||||
|
||||
export class ReflexManager {
|
||||
constructor(
|
||||
@@ -12,15 +12,15 @@ export class ReflexManager {
|
||||
) {}
|
||||
|
||||
public init(bot: MineflayerWithAgents): void {
|
||||
// Listen to user intents as a "subconscious" filter
|
||||
this.deps.eventManager.on<UserIntentPayload>('user_intent', (event) => {
|
||||
this.handleUserIntent(bot, event)
|
||||
// Listen to stimuli as a "subconscious" filter
|
||||
this.deps.eventManager.on<StimulusPayload>('stimulus', (event) => {
|
||||
this.onStimulus(bot, event)
|
||||
})
|
||||
|
||||
// TODO: Listen to world_update for physical reflexes (dodge, flee)
|
||||
}
|
||||
|
||||
private handleUserIntent(bot: MineflayerWithAgents, event: BotEvent<UserIntentPayload>): void {
|
||||
private onStimulus(bot: MineflayerWithAgents, event: BotEvent<StimulusPayload>): void {
|
||||
const { content } = event.payload
|
||||
const lowerContent = content.toLowerCase().trim()
|
||||
|
||||
|
||||
@@ -23,16 +23,16 @@ export interface MineflayerWithAgents extends Mineflayer {
|
||||
chat: ChatAgent
|
||||
}
|
||||
|
||||
export interface LLMAgentOptions {
|
||||
export interface CognitiveEngineOptions {
|
||||
agent: Neuri
|
||||
airiClient: Client
|
||||
}
|
||||
|
||||
export type EventType = 'user_intent' | 'world_update' | 'system_alert'
|
||||
export type EventType = 'stimulus' | 'perception' | 'feedback' | 'world_update' | 'system_alert'
|
||||
|
||||
export interface BotEventSource {
|
||||
type: 'minecraft' | 'airi' | 'system'
|
||||
id: string // username or session id
|
||||
id: string // Agent/Source identifier
|
||||
reply?: (message: string) => void
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ export interface BotEvent<T = any> {
|
||||
handled?: boolean // Set by Reflex layer to inhibit Conscious layer
|
||||
}
|
||||
|
||||
export interface UserIntentPayload {
|
||||
export interface StimulusPayload {
|
||||
content: string
|
||||
metadata?: {
|
||||
entity?: any // prismarine-entity Entity
|
||||
|
||||
@@ -9,7 +9,7 @@ import { pathfinder as MineflayerPathfinder } from 'mineflayer-pathfinder'
|
||||
import { plugin as MineflayerPVP } from 'mineflayer-pvp'
|
||||
import { plugin as MineflayerTool } from 'mineflayer-tool'
|
||||
|
||||
import { LLMAgent } from './cognitive'
|
||||
import { CognitiveEngine } from './cognitive'
|
||||
import { initBot } from './composables/bot'
|
||||
import { config, initEnv } from './composables/config'
|
||||
import { createNeuriAgent } from './composables/neuri'
|
||||
@@ -44,9 +44,9 @@ async function main() {
|
||||
url: config.airi.wsBaseUrl,
|
||||
})
|
||||
|
||||
// Dynamically load LLMAgent after the bot is initialized
|
||||
// Dynamically load CognitiveEngine after the bot is initialized
|
||||
const agent = await createNeuriAgent(bot)
|
||||
await bot.loadPlugin(LLMAgent({ agent, airiClient }))
|
||||
await bot.loadPlugin(CognitiveEngine({ agent, airiClient }))
|
||||
|
||||
process.on('SIGINT', () => {
|
||||
bot.stop()
|
||||
|
||||
Reference in New Issue
Block a user