diff --git a/services/minecraft/README.md b/services/minecraft/README.md index 4813f9552..51123be7c 100644 --- a/services/minecraft/README.md +++ b/services/minecraft/README.md @@ -56,7 +56,7 @@ The perception layer acts as the sensory input hub, collecting raw Mineflayer si **Pipeline**: - Event definitions in `events/definitions/*` bind Mineflayer events to normalized raw events. -- `EventRegistry` emits `raw::` events to the Cognitive EventBus. +- `EventRegistry` emits `raw::` events to the cognitive event bus. - `RuleEngine` evaluates YAML rules and emits derived `signal:*` events consumed by Reflex/Conscious layers. **Key files**: @@ -149,7 +149,7 @@ src/ │ │ ├── action-registry.ts # Tool dispatch + schema validation │ │ ├── llm-actions.ts # Tool catalog │ │ └── types.ts -│ ├── os/ # EventBus + tracing core +│ ├── event-bus.ts # Event bus core │ ├── container.ts # Dependency injection wiring │ ├── index.ts # Cognitive system entrypoint │ └── types.ts # Shared cognitive types diff --git a/services/minecraft/codex-skills/minecraft-debug-mcp/SKILL.md b/services/minecraft/codex-skills/minecraft-debug-mcp/SKILL.md index bb5c162c6..5e0ebc63d 100644 --- a/services/minecraft/codex-skills/minecraft-debug-mcp/SKILL.md +++ b/services/minecraft/codex-skills/minecraft-debug-mcp/SKILL.md @@ -11,7 +11,7 @@ Use this skill to run the local bot and interact with its MCP debug interface sa ## Quick Start Workflow -1. Run `pnpm dev` from `/Users/rinshinohara/Repo/airi/services/minecraft` and keep it running. +1. Run `pnpm dev` from `/path/to/project/root/services/minecraft` and keep it running. 2. Wait for `MCP REPL server running at http://localhost:3001` in logs. 3. Connect MCP client to `http://localhost:3001/sse`. 4. Verify readiness with a read-only call: diff --git a/services/minecraft/codex-skills/minecraft-debug-mcp/references/mcp-surface.md b/services/minecraft/codex-skills/minecraft-debug-mcp/references/mcp-surface.md index cd9fb0bbe..74ab879c9 100644 --- a/services/minecraft/codex-skills/minecraft-debug-mcp/references/mcp-surface.md +++ b/services/minecraft/codex-skills/minecraft-debug-mcp/references/mcp-surface.md @@ -1,6 +1,6 @@ # Minecraft Debug MCP Surface -Implementation source: `/Users/rinshinohara/Repo/airi/services/minecraft/src/debug/mcp-repl-server.ts`. +Implementation source: `/path/to/project/root/services/minecraft/src/debug/mcp-repl-server.ts`. ## Endpoint @@ -9,7 +9,7 @@ Implementation source: `/Users/rinshinohara/Repo/airi/services/minecraft/src/deb - SSE fallback endpoint: `GET /sse` + `POST /messages` The bot starts this server during normal runtime from: -- `/Users/rinshinohara/Repo/airi/services/minecraft/src/cognitive/index.ts` +- `/path/to/project/root/services/minecraft/src/cognitive/index.ts` ## Resources diff --git a/services/minecraft/src/cognitive/conscious/brain.ts b/services/minecraft/src/cognitive/conscious/brain.ts index cbd44e334..41d13ee3e 100644 --- a/services/minecraft/src/cognitive/conscious/brain.ts +++ b/services/minecraft/src/cognitive/conscious/brain.ts @@ -4,7 +4,7 @@ import type { Message } from '@xsai/shared-chat' import type { Action } from '../../libs/mineflayer/action' import type { TaskExecutor } from '../action/task-executor' import type { ActionInstruction } from '../action/types' -import type { EventBus, TracedEvent } from '../os' +import type { EventBus, TracedEvent } from '../event-bus' import type { PerceptionSignal } from '../perception/types/signals' import type { ReflexManager } from '../reflex/reflex-manager' import type { BotEvent, MineflayerWithAgents } from '../types' diff --git a/services/minecraft/src/cognitive/container.ts b/services/minecraft/src/cognitive/container.ts index 6bee63d64..f1f9f6e21 100644 --- a/services/minecraft/src/cognitive/container.ts +++ b/services/minecraft/src/cognitive/container.ts @@ -1,6 +1,6 @@ import type { Logg } from '@guiiai/logg' -import type { EventBus } from './os' +import type { EventBus } from './event-bus' import type { RuleEngine } from './perception/rules' import { useLogg } from '@guiiai/logg' @@ -10,7 +10,7 @@ import { config } from '../composables/config' import { TaskExecutor } from './action/task-executor' import { Brain } from './conscious/brain' import { LLMAgent } from './conscious/llm-agent' -import { createEventBus } from './os' +import { createEventBus } from './event-bus' import { PerceptionPipeline } from './perception/pipeline' import { createRuleEngine } from './perception/rules' import { ReflexManager } from './reflex/reflex-manager' @@ -44,13 +44,8 @@ export function createAgentContainer() { model: config.openai.model, })).singleton(), - // Register EventBus (Cognitive OS core) - eventBus: asFunction(() => - createEventBus({ - logger: useLogg('eventBus').useGlobalConfig(), - config: { historySize: 10000 }, - }), - ).singleton(), + // Register EventBus (cognitive event core) + eventBus: asFunction(() => createEventBus()).singleton(), // Register RuleEngine (YAML rules processing) ruleEngine: asFunction(({ eventBus }) => { diff --git a/services/minecraft/src/cognitive/os/event-bus.test.ts b/services/minecraft/src/cognitive/event-bus.test.ts similarity index 69% rename from services/minecraft/src/cognitive/os/event-bus.test.ts rename to services/minecraft/src/cognitive/event-bus.test.ts index 0615d6e79..b6d16e5b6 100644 --- a/services/minecraft/src/cognitive/os/event-bus.test.ts +++ b/services/minecraft/src/cognitive/event-bus.test.ts @@ -1,16 +1,11 @@ -import type { TracedEvent } from './types' +import type { TracedEvent } from './event-bus' -import { useLogg } from '@guiiai/logg' import { describe, expect, it, vi } from 'vitest' -import { createEventBus } from './index' +import { createEventBus } from './event-bus' describe('eventBus', () => { - const createTestBus = () => - createEventBus({ - logger: useLogg('test'), - config: { historySize: 100 }, - }) + const createTestBus = () => createEventBus() describe('emit', () => { it('should create an event with auto-generated id and timestamp', () => { @@ -164,7 +159,7 @@ describe('eventBus', () => { payload: {}, source: { component: 'test' }, }) - expect(handler).toHaveBeenCalledTimes(1) // Still 1 + expect(handler).toHaveBeenCalledTimes(1) }) }) @@ -174,7 +169,6 @@ describe('eventBus', () => { let childEvent: TracedEvent | undefined bus.subscribe('parent:event', () => { - // Emit within handler - should inherit context childEvent = bus.emit({ type: 'child:event', payload: {}, @@ -193,50 +187,4 @@ describe('eventBus', () => { expect(childEvent!.parentId).toBe(parent.id) }) }) - - describe('history', () => { - it('should store events in history', () => { - const bus = createTestBus() - - bus.emit({ type: 'e1', payload: {}, source: { component: 'test' } }) - bus.emit({ type: 'e2', payload: {}, source: { component: 'test' } }) - bus.emit({ type: 'e3', payload: {}, source: { component: 'test' } }) - - const history = bus.getHistory() - expect(history.length).toBe(3) - expect(history[0].type).toBe('e1') - expect(history[2].type).toBe('e3') - }) - - it('should respect historySize limit (ring buffer)', () => { - const bus = createEventBus({ - logger: useLogg('test'), - config: { historySize: 3 }, - }) - - bus.emit({ type: 'e1', payload: {}, source: { component: 'test' } }) - bus.emit({ type: 'e2', payload: {}, source: { component: 'test' } }) - bus.emit({ type: 'e3', payload: {}, source: { component: 'test' } }) - bus.emit({ type: 'e4', payload: {}, source: { component: 'test' } }) - - const history = bus.getHistory() - expect(history.length).toBe(3) - // Oldest event (e1) should be evicted - expect(history.map(e => e.type)).toEqual(['e2', 'e3', 'e4']) - }) - }) - - describe('getEventsByTrace', () => { - it('should filter events by traceId', () => { - const bus = createTestBus() - - const e1 = bus.emit({ type: 'a', payload: {}, source: { component: 'test' } }) - bus.emitChild(e1, { type: 'b', payload: {}, source: { component: 'test' } }) - bus.emit({ type: 'c', payload: {}, source: { component: 'test' } }) // Different trace - - const trace = bus.getEventsByTrace(e1.traceId) - expect(trace.length).toBe(2) - expect(trace.map(e => e.type)).toEqual(['a', 'b']) - }) - }) }) diff --git a/services/minecraft/src/cognitive/event-bus.ts b/services/minecraft/src/cognitive/event-bus.ts new file mode 100644 index 000000000..b83d74050 --- /dev/null +++ b/services/minecraft/src/cognitive/event-bus.ts @@ -0,0 +1,175 @@ +import { AsyncLocalStorage } from 'node:async_hooks' + +import { nanoid } from 'nanoid' + +export type EventId = string +export type TraceId = string + +export interface EventSource { + readonly component: string + readonly id?: string +} + +export interface TracedEvent { + readonly id: EventId + readonly traceId: TraceId + readonly parentId?: EventId + readonly type: string + readonly payload: Readonly + readonly timestamp: number + readonly source: EventSource +} + +export interface EventInput { + readonly type: string + readonly payload: Readonly + readonly source: EventSource + readonly traceId?: string + readonly parentId?: string +} + +export type EventHandler = (event: TracedEvent) => void +export type Unsubscribe = () => void +export type EventPattern = string + +interface TraceContext { + traceId: string + parentId?: string +} + +interface Subscription { + pattern: EventPattern + handler: EventHandler +} + +const traceStorage = new AsyncLocalStorage() + +function generateEventId(): string { + return nanoid(12) +} + +function generateTraceId(): string { + return nanoid(16) +} + +function matchesPattern(pattern: EventPattern, eventType: string): boolean { + if (pattern === '*') + return true + + if (pattern.endsWith(':*')) { + const prefix = pattern.slice(0, -1) + return eventType.startsWith(prefix) + } + + return pattern === eventType +} + +function deepFreeze(value: T): T { + if (value === null || typeof value !== 'object' || Object.isFrozen(value)) + return value + + if (Array.isArray(value)) { + for (const item of value) + deepFreeze(item) + return Object.freeze(value) + } + + for (const child of Object.values(value as Record)) + deepFreeze(child) + + return Object.freeze(value) +} + +function resolveTraceContext(input: Pick): TraceContext { + if (input.traceId) { + return Object.freeze({ + traceId: input.traceId, + parentId: input.parentId, + }) + } + + const inherited = traceStorage.getStore() + if (inherited) { + return Object.freeze({ + traceId: inherited.traceId, + parentId: inherited.parentId, + }) + } + + return Object.freeze({ traceId: generateTraceId() }) +} + +function withTraceContext(traceId: string, parentId: string, fn: () => T): T { + return traceStorage.run({ traceId, parentId }, fn) +} + +export class EventBus { + private readonly subscriptions = new Map() + private nextSubId = 0 + + public emit(input: EventInput): TracedEvent { + const trace = resolveTraceContext({ + traceId: input.traceId, + parentId: input.parentId, + }) + + const event = deepFreeze({ + id: generateEventId(), + traceId: trace.traceId, + parentId: trace.parentId, + type: input.type, + payload: input.payload, + timestamp: Date.now(), + source: input.source, + } satisfies TracedEvent) + + this.dispatch(event) + return event + } + + public emitChild( + parent: TracedEvent, + input: Omit, 'traceId' | 'parentId'>, + ): TracedEvent { + return this.emit({ + ...input, + traceId: parent.traceId, + parentId: parent.id, + }) + } + + public subscribe( + pattern: EventPattern, + handler: EventHandler, + ): Unsubscribe { + const id = this.nextSubId++ + this.subscriptions.set(id, { + pattern, + handler: handler as EventHandler, + }) + + return () => { + this.subscriptions.delete(id) + } + } + + private dispatch(event: TracedEvent): void { + for (const sub of this.subscriptions.values()) { + if (!matchesPattern(sub.pattern, event.type)) + continue + + try { + withTraceContext(event.traceId, event.id, () => { + sub.handler(event) + }) + } + catch { + // Keep dispatch resilient by isolating subscriber failures. + } + } + } +} + +export function createEventBus(): EventBus { + return new EventBus() +} diff --git a/services/minecraft/src/cognitive/os/event-bus.ts b/services/minecraft/src/cognitive/os/event-bus.ts deleted file mode 100644 index c44a05f66..000000000 --- a/services/minecraft/src/cognitive/os/event-bus.ts +++ /dev/null @@ -1,273 +0,0 @@ -import type { Logg } from '@guiiai/logg' - -import type { - EventBusConfig, - EventBusSnapshot, - EventHandler, - EventInput, - EventPattern, - Subscription, - TraceContext, - TracedEvent, - Unsubscribe, -} from './types' - -import { - deriveTraceContext, - generateEventId, - resolveTraceContext, - runWithTraceContext, -} from './tracer' -import { freezeEvent } from './types' - -/** - * Default EventBus configuration - */ -const DEFAULT_CONFIG: EventBusConfig = Object.freeze({ - historySize: 10000, -}) - -/** - * Check if an event type matches a pattern - * Supports wildcards: 'raw:*' matches 'raw:sighted:punch' - */ -function matchesPattern(pattern: EventPattern, eventType: string): boolean { - if (pattern === '*') - return true - - if (pattern.endsWith(':*')) { - const prefix = pattern.slice(0, -1) // Remove the '*' - return eventType.startsWith(prefix) - } - - return pattern === eventType -} - -/** - * EventBus - The heart of the Cognitive OS - * - * This is the ONLY component with mutable internal state. - * All other components should be pure functions that interact - * through the EventBus. - * - * Design principles: - * - Events are immutable once created - * - Trace context automatically propagates through handlers - * - Ring buffer prevents memory leaks - * - Pattern-based subscriptions for flexible routing - */ -export class EventBus { - // Internal mutable state - isolated from the outside world - private readonly buffer: (TracedEvent | null)[] = [] - private readonly subscriptions = new Map() - private nextSubId = 0 - private writeIndex = 0 // Next position to write - private count = 0 // Number of events stored - - constructor( - private readonly deps: { - logger: Logg - config?: Partial - }, - ) { - // Pre-allocate buffer - const size = this.config.historySize - this.buffer = new Array(size).fill(null) - } - - private get config(): EventBusConfig { - return { ...DEFAULT_CONFIG, ...this.deps.config } - } - - /** - * Emit an event to the bus - * - * This is the ONLY side effect entry point. - * Returns the created event (immutable). - */ - public emit(input: EventInput): TracedEvent { - // Resolve trace context (from explicit, async context, or new) - const trace = resolveTraceContext({ - traceId: input.traceId, - parentId: input.parentId, - }) - - // Create the full event - const event = freezeEvent({ - id: generateEventId(), - traceId: trace.traceId, - parentId: trace.parentId, - type: input.type, - payload: input.payload, - timestamp: Date.now(), - source: input.source, - }) - - // Store in ring buffer - this.storeEvent(event) - - // Dispatch to subscribers - this.dispatch(event) - - return event - } - - /** - * Emit an event as a child of another event - * Automatically sets up trace context - */ - public emitChild( - parent: TracedEvent, - input: Omit, 'traceId' | 'parentId'>, - ): TracedEvent { - return this.emit({ - ...input, - traceId: parent.traceId, - parentId: parent.id, - }) - } - - /** - * Subscribe to events matching a pattern - * Returns an unsubscribe function - */ - public subscribe( - pattern: EventPattern, - handler: EventHandler, - ): Unsubscribe { - const id = this.nextSubId++ - this.subscriptions.set(id, { - pattern, - handler: handler as EventHandler, - }) - - return () => { - this.subscriptions.delete(id) - } - } - - /** - * Get event history as an immutable array - * Events are returned in chronological order (oldest first) - */ - public getHistory(): readonly TracedEvent[] { - const size = this.config.historySize - - if (this.count === 0) { - return [] - } - - const result: TracedEvent[] = [] - - // Calculate start position (oldest event) - // If buffer is full, oldest is at writeIndex - // If not full, oldest is at 0 - const startIdx = this.count < size ? 0 : this.writeIndex - - for (let i = 0; i < this.count; i++) { - const idx = (startIdx + i) % size - const event = this.buffer[idx] - if (event) { - result.push(event) - } - } - - return Object.freeze(result) - } - - /** - * Get debug snapshot - */ - public getSnapshot(): EventBusSnapshot { - return Object.freeze({ - events: this.getHistory(), - subscriptionCount: this.subscriptions.size, - }) - } - - /** - * Replay a sequence of events - * Used for debugging and testing - */ - public replay(events: readonly TracedEvent[]): void { - this.deps.logger.withFields({ count: events.length }).log('EventBus: replaying events') - - for (const event of events) { - // Store without re-generating IDs - this.storeEvent(event) - // Dispatch to current subscribers - this.dispatch(event) - } - } - - /** - * Clear all events (for testing) - */ - public clear(): void { - this.buffer.fill(null) - this.writeIndex = 0 - this.count = 0 - } - - /** - * Get events by trace ID - */ - public getEventsByTrace(traceId: string): readonly TracedEvent[] { - return Object.freeze( - this.getHistory().filter(e => e.traceId === traceId), - ) - } - - // ============================================================ - // Private methods - // ============================================================ - - private storeEvent(event: TracedEvent): void { - const size = this.config.historySize - - // Write to current position - this.buffer[this.writeIndex] = event - - // Advance write position - this.writeIndex = (this.writeIndex + 1) % size - - // Update count (max is buffer size) - if (this.count < size) { - this.count++ - } - } - - private dispatch(event: TracedEvent): void { - // Create trace context for handlers - const childContext: TraceContext = deriveTraceContext(event.traceId, event.id) - - for (const sub of this.subscriptions.values()) { - if (!matchesPattern(sub.pattern, event.type)) - continue - - try { - // Run handler within trace context so child emissions inherit it - runWithTraceContext(childContext, () => { - sub.handler(event) - }) - } - catch (err) { - this.deps.logger - .withError(err as Error) - .withFields({ eventType: event.type, pattern: sub.pattern }) - .error('EventBus: handler error') - } - } - } -} - -/** - * Create an EventBus instance - * Factory function for cleaner API - */ -export function createEventBus(deps: { - logger: Logg - config?: Partial -}): EventBus { - return new EventBus(deps) -} diff --git a/services/minecraft/src/cognitive/os/index.ts b/services/minecraft/src/cognitive/os/index.ts deleted file mode 100644 index 960483877..000000000 --- a/services/minecraft/src/cognitive/os/index.ts +++ /dev/null @@ -1,43 +0,0 @@ -/** - * Cognitive OS - Event-sourced architecture for the cognitive engine - * - * Core principles: - * - All state changes go through TracedEvents - * - Events are immutable - * - Trace context propagates automatically - * - EventBus is the only mutable container - */ - -// NOTE: RuleEngine and rule utilities moved to cognitive/perception/rules. - -// EventBus -export { createEventBus, EventBus } from './event-bus' - -// Tracer utilities -export { - createTraceContext, - deriveTraceContext, - generateEventId, - generateTraceId, - getCurrentTraceContext, - resolveTraceContext, - runWithTraceContext, -} from './tracer' - -// Core types -export type { - EventBusConfig, - EventBusSnapshot, - EventHandler, - EventId, - EventInput, - EventPattern, - EventSource, - Subscription, - TraceContext, - TracedEvent, - TraceId, - Unsubscribe, -} from './types' - -export { freezeEvent } from './types' diff --git a/services/minecraft/src/cognitive/os/tracer.ts b/services/minecraft/src/cognitive/os/tracer.ts deleted file mode 100644 index 0185ff63e..000000000 --- a/services/minecraft/src/cognitive/os/tracer.ts +++ /dev/null @@ -1,98 +0,0 @@ -import type { EventId, TraceContext, TraceId } from './types' - -/** - * AsyncLocalStorage-based trace context propagation - * This allows handlers to automatically inherit trace context - */ -import { AsyncLocalStorage } from 'node:async_hooks' - -import { nanoid } from 'nanoid' - -/** - * Generate a unique event ID - * Uses nanoid for compact, URL-safe IDs - */ -export function generateEventId(): EventId { - return nanoid(12) -} - -/** - * Generate a unique trace ID - */ -export function generateTraceId(): TraceId { - return nanoid(16) -} - -/** - * Create a new trace context for a fresh event chain - */ -export function createTraceContext(): TraceContext { - return Object.freeze({ - traceId: generateTraceId(), - }) -} - -/** - * Derive a child trace context from a parent event - * Preserves the same traceId but sets the parentId - */ -export function deriveTraceContext( - parentTraceId: TraceId, - parentEventId: EventId, -): TraceContext { - return Object.freeze({ - traceId: parentTraceId, - parentId: parentEventId, - }) -} - -const traceStorage = new AsyncLocalStorage() - -/** - * Get the current trace context from async local storage - * Returns undefined if not in a traced context - */ -export function getCurrentTraceContext(): TraceContext | undefined { - return traceStorage.getStore() -} - -/** - * Run a function within a trace context - * All events emitted within this context will inherit the trace - */ -export function runWithTraceContext( - context: TraceContext, - fn: () => T, -): T { - return traceStorage.run(context, fn) -} - -/** - * Create or derive trace context for an event - * If we're in a traced context, derive from it; otherwise create new - */ -export function resolveTraceContext( - explicit?: Partial, -): TraceContext { - const current = getCurrentTraceContext() - - if (explicit?.traceId) { - // Explicit context provided - return Object.freeze({ - traceId: explicit.traceId, - parentId: explicit.parentId, - }) - } - - if (current) { - // Derive from current async context - // Note: parentId should be set by the caller who knows the parent event - return Object.freeze({ - traceId: current.traceId, - parentId: current.parentId, - }) - } - - // New trace - return createTraceContext() -} diff --git a/services/minecraft/src/cognitive/os/types.ts b/services/minecraft/src/cognitive/os/types.ts deleted file mode 100644 index e1e5a8183..000000000 --- a/services/minecraft/src/cognitive/os/types.ts +++ /dev/null @@ -1,139 +0,0 @@ -/** - * Core types for the Cognitive OS event-sourced architecture. - * All types are immutable by design (Readonly). - */ - -/** - * Unique identifier for events and traces - */ -export type EventId = string -export type TraceId = string - -/** - * Event source identifier - */ -export interface EventSource { - readonly component: string - readonly id?: string -} - -/** - * A traced event - the core unit of the event-sourced system. - * All fields are readonly to enforce immutability. - */ -export interface TracedEvent { - /** Unique event ID */ - readonly id: EventId - /** Trace ID shared across related events */ - readonly traceId: TraceId - /** Parent event ID (if derived from another event) */ - readonly parentId?: EventId - /** Event type identifier (e.g. 'raw:sighted:arm_swing') */ - readonly type: string - /** Event payload - should be immutable */ - readonly payload: Readonly - /** Event timestamp */ - readonly timestamp: number - /** Source component */ - readonly source: EventSource -} - -/** - * Input for creating a new event - * traceId and parentId are optional - will be auto-generated or inherited from context - * id and timestamp are always auto-generated - */ -export interface EventInput { - readonly type: string - readonly payload: Readonly - readonly source: EventSource - readonly traceId?: string - readonly parentId?: string -} - -/** - * Event handler function - should be a pure function that may emit new events - */ -export type EventHandler = (event: TracedEvent) => void - -/** - * Unsubscribe function returned by subscribe - */ -export type Unsubscribe = () => void - -/** - * Event pattern for subscription filtering - * Supports wildcards: 'raw:*' matches 'raw:sighted:punch' - */ -export type EventPattern = string - -/** - * Subscription record - */ -export interface Subscription { - readonly pattern: EventPattern - readonly handler: EventHandler -} - -/** - * EventBus configuration - */ -export interface EventBusConfig { - /** Maximum events to keep in history (ring buffer) */ - readonly historySize: number -} - -/** - * Snapshot of EventBus state for debugging - */ -export interface EventBusSnapshot { - readonly events: readonly TracedEvent[] - readonly subscriptionCount: number -} - -/** - * Trace context for propagating trace information - */ -export interface TraceContext { - readonly traceId: TraceId - readonly parentId?: EventId -} - -/** - * Deep freeze an object (recursively freeze all nested objects) - * Performance note: Use sparingly on large objects - */ -export function deepFreeze(obj: T): Readonly { - if (obj === null || typeof obj !== 'object') { - return obj - } - - // Don't freeze already frozen objects - if (Object.isFrozen(obj)) { - return obj - } - - // Freeze arrays - if (Array.isArray(obj)) { - obj.forEach(item => deepFreeze(item)) - return Object.freeze(obj) as Readonly - } - - // Freeze object properties - Object.keys(obj).forEach((key) => { - const value = (obj as Record)[key] - if (value !== null && typeof value === 'object') { - deepFreeze(value) - } - }) - - return Object.freeze(obj) -} - -/** - * Create an immutable event by deep freezing all its properties - * This ensures the entire object tree is immutable - */ -export function freezeEvent(event: TracedEvent): TracedEvent { - return deepFreeze(event) -} diff --git a/services/minecraft/src/cognitive/perception/pipeline.ts b/services/minecraft/src/cognitive/perception/pipeline.ts index 10f8cecf0..0cb4a5114 100644 --- a/services/minecraft/src/cognitive/perception/pipeline.ts +++ b/services/minecraft/src/cognitive/perception/pipeline.ts @@ -1,6 +1,6 @@ import type { Logg } from '@guiiai/logg' -import type { EventBus } from '../os' +import type { EventBus } from '../event-bus' import type { MineflayerWithAgents } from '../types' import { EventRegistry } from './events' diff --git a/services/minecraft/src/cognitive/perception/rules/engine.ts b/services/minecraft/src/cognitive/perception/rules/engine.ts index 3d700ea72..c7dee5c28 100644 --- a/services/minecraft/src/cognitive/perception/rules/engine.ts +++ b/services/minecraft/src/cognitive/perception/rules/engine.ts @@ -7,7 +7,7 @@ import type { Logg } from '@guiiai/logg' -import type { EventBus, TracedEvent } from '../../os' +import type { EventBus, TracedEvent } from '../../event-bus' import type { AccumulatorsState, ParsedRule, diff --git a/services/minecraft/src/cognitive/reflex/reflex-manager.ts b/services/minecraft/src/cognitive/reflex/reflex-manager.ts index c1cc94bf7..86859327d 100644 --- a/services/minecraft/src/cognitive/reflex/reflex-manager.ts +++ b/services/minecraft/src/cognitive/reflex/reflex-manager.ts @@ -1,7 +1,7 @@ import type { Logg } from '@guiiai/logg' import type { TaskExecutor } from '../action/task-executor' -import type { EventBus, TracedEvent } from '../os' +import type { EventBus, TracedEvent } from '../event-bus' import type { PerceptionSignal } from '../perception/types/signals' import type { MineflayerWithAgents } from '../types' import type { ReflexContextState } from './context' diff --git a/services/minecraft/src/debug/types.ts b/services/minecraft/src/debug/types.ts index c1c89b22a..b645d5809 100644 --- a/services/minecraft/src/debug/types.ts +++ b/services/minecraft/src/debug/types.ts @@ -66,7 +66,7 @@ export interface ReflexStateEvent { } /** - * Traced event from the Cognitive OS EventBus + * Traced event from the cognitive event bus */ export interface TraceEvent { /** Unique event ID */