Files
PenlunaRinautofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
b3fac81c5a feat(minecraft): desktop relay via a Minecraft adapter (#1916)
> **Reworked.** This PR has been rebuilt around the neutral Context Flow
architecture, per @shinohara-rin's review. Minecraft is no longer
special-cased in the generic stage-ui runtime — desktop relay &
read-aloud are now reintroduced through a **Minecraft adapter** that
contributes into the existing generic stores.

## Stacked PRs (please review/merge in order)

This rework is split as you suggested — "first restore
`services/minecraft` to only own Minecraft semantics, then reintroduce
desktop relay/read-aloud through ... a Minecraft adapter":

1. **#1949** — generic stage-ui robustness fixes (spark:command result
guard + TTS session isolation), split out as you noted they were
separable.
2. **#1950** — `refactor(minecraft)`: restore `services/minecraft` to
neutral Minecraft semantics (removes the desktop-relay assumptions baked
into the merged #1915 — `handleActionIntent`'s
`username='主人'`/`relayedFrom`, the `master:` status hint, and the
`minecraft:speech` forwarding).
3. **this PR** — reintroduces desktop relay & read-aloud via the
Minecraft adapter.

Because #1949 and #1950 are not merged yet, their commits currently
appear in this PR's diff. Once they land I'll rebase this PR onto `main`
so the diff shrinks to just the adapter work.

## The adapter (`apps/stage-tamagotchi/src/renderer/stores/minecraft/`)

The renderer owns the entire desktop ↔ in-game-bot integration and
contributes into the **existing** generic stores — the same pattern as
`mcp-tools.ts` / `plugin-tools.ts`:

- **`relayToMinecraft` tool** →
`useLlmToolsStore.registerTools('minecraft', …)`, registered **only
while the bot is online** (a hard capability gate, replacing the old
prompt-only "don't relay when offline"). `execute()` re-checks
availability, so a relay is never acked after the bot disconnects.
- **Persona directive** →
`useLlmToolsetPromptsStore.registerToolsetPrompts('minecraft', …)`,
re-registered whenever online/master/runtime-context change so the model
gets a fresh directive each turn.
- **Read-aloud** → consumes the bot's `minecraft:speech` chat into the
stage TTS (Chinese-gated), and binds 主人 by **parsing the bot's neutral
status text** — no desktop-specific hint from the bot service.
- **Notify muting** →
`orchestratorStore.muteNotifySource('minecraft-bot')`.

## Generic, non-Minecraft additions

- **`useSystemSpeechStore`** (stage-ui): a neutral bridge so any module
can voice a one-off system line; `Stage.vue` consumes it via
independent, tracked TTS sessions cancelled on unmount /
provider-or-voice change.
- **`orchestrator.muteNotifySource(id)`**: a generic primitive so a
module suppresses only **its own** notifies — every other module/plugin
notify still reacts (this fixes the earlier P1 where all
`character`-targeted notifies were dropped).
- **`./tools/*` export** from stage-ui so app-side tool authors can
reuse the shared spark-command normalizers.

## services/minecraft

Re-adds the bot's own-chat forwarding on `minecraft:speech`, now landing
**together with** its adapter consumer so the read-aloud contract is
never half-present on `main`.

## How tested

- `pnpm -F @proj-airi/stage-ui typecheck` + `pnpm -F
@proj-airi/stage-tamagotchi typecheck` → 0 errors.
- 16 new unit tests (persona prompt builder + relay tool: availability
gate, do/stop, full-label fidelity, master parsing, read-aloud gating);
orchestrator suite 5/5.
- `eslint` → 0 problems.

## Addressed review points

- Restore non-Minecraft notifications → generic `muteNotifySource` (only
the bot's source is muted).
- Isolate / track-and-cancel one-off system TTS sessions → `Stage.vue`
`oneOffSessions`.
- Re-check bot availability before relaying → `isAvailable()` in
`execute()`.
- Read the master hint that actually exists → desktop now parses the
master from neutral status **text** (the `master:` hint is removed in
#1950).
- Defer Minecraft init until after channel config → adapter `setup()`
runs after the configured `serverChannelStore.initialize(...)`.

---------

Co-authored-by: Rin <shinohara-rin@users.noreply.github.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-10 15:30:45 +08:00
..

AIRI Minecraft Service

This workspace runs AIRI's dedicated Minecraft bot. It connects a Mineflayer runtime to a Minecraft server, loads the cognitive stack in src/cognitive, and bridges status, context, and command traffic back to AIRI so the Stage settings shell can observe the service.

Deprecation Notice

This service is on a deprecation path. The current Mineflayer-based bot is expected to be replaced by a Fabric mod based runtime, which will become the primary Minecraft integration surface going forward.

Use this service for current local development and maintenance, but avoid building new long-term features around the Mineflayer runtime unless they are also part of the migration plan.

Safety Notice

Do not connect this bot to public servers you do not trust.

The runtime can execute JavaScript-generated action plans to control the bot. Those scripts run in an isolated environment, but they still drive a real local process with access to your Minecraft session, local network reachability, and other machine-side resources. A malicious or hostile server can still cause unwanted actions, or damage to your system.

Treat this service as a local-development and trusted-server tool only.

Setup

  1. Install workspace dependencies from the repo root:

    pnpm i
    
  2. Copy the template:

    cp integrations/minecraft/.env integrations/minecraft/.env.local
    
  3. Edit integrations/minecraft/.env.local.

  4. Start the service:

    pnpm -F @proj-airi/minecraft-bot dev
    

    Or, from integrations/minecraft/:

    pnpm dev
    
  5. The bot should automatically connect to both AIRI and the Minecraft server.

Cognitive Architecture

AIRI's Minecraft agent is built on a four-layered cognitive architecture inspired by cognitive science, enabling reactive, conscious, and physically grounded behaviors.

Architecture Overview

graph TB
    subgraph "Layer A: Perception"
        Events[Raw Events]
        EM[Event Manager]
        Events --> EM
    end

    subgraph "Layer B: Reflex (Subconscious)"
        RM[Reflex Manager]
        FSM[State Machine]
        RM --> FSM
    end

    subgraph "Layer C: Conscious (Reasoning)"
        ORC[Orchestrator]
        Planner[Planning Agent (LLM)]
        Chat[Chat Agent (LLM)]
        ORC --> Planner
        ORC --> Chat
    end

    subgraph "Layer D: Action (Execution)"
        TE[Task Executor]
        AA[Action Agent]
        Planner -->|Plan| TE
        TE -->|Action Steps| AA
    end

    EM -->|High Priority| RM
    EM -->|All Events| ORC
    RM -.->|Inhibition Signal| ORC
    ORC -->|Execution Request| TE

    style EM fill:#e1f5ff
    style RM fill:#fff4e1
    style ORC fill:#ffe1f5
    style TE fill:#dcedc8

Layer A: Perception

Location: src/cognitive/perception/

The perception layer acts as the sensory input hub, collecting raw Mineflayer signals and translating them into typed events/signals through an event registry + rule engine pipeline.

Pipeline:

  • Event definitions in events/definitions/* bind Mineflayer events to normalized raw events.
  • EventRegistry emits raw:<modality>:<kind> events to the cognitive event bus.
  • RuleEngine evaluates YAML rules and emits derived signal:* events consumed by Reflex/Conscious layers.

Key files:

  • events/index.ts
  • events/definitions/*
  • rules/engine.ts
  • rules/*.yaml
  • pipeline.ts

Layer B: Reflex

Location: src/cognitive/reflex/

The reflex layer handles immediate, instinctive reactions. It operates on a finite state machine (FSM) pattern for predictable, fast responses.

Components:

  • Reflex Manager (reflex-manager.ts): Coordinates reflex behaviors
  • Inhibition: Reflexes can inhibit Conscious layer processing to prevent redundant responses.

Layer C: Conscious

Location: src/cognitive/conscious/

The conscious layer handles complex reasoning, planning, and high-level decision-making. No physical execution happens here anymore.

Components:

  • Brain (brain.ts): Event queue orchestration, LLM turn lifecycle, safety/budget guards, debug REPL integration.
  • JavaScript Planner (js-planner.ts): Sandboxed planning/runtime execution against exposed tools/globals.
  • Query Runtime (query-dsl.ts): Read-only world/inventory/entity query helpers for planner scripts.
  • Task State (task-state.ts): Cancellation token and task lifecycle primitives used by action execution.

Layer D: Action

Location: src/cognitive/action/

The action layer is responsible for the actual execution of tasks in the world. It isolates "Doing" from "Thinking".

Components:

  • Task Executor (task-executor.ts): Runs normalized action instructions and emits action lifecycle events.
  • Action Registry (action-registry.ts): Validates params and dispatches tool calls.
  • Tool Catalog (llm-actions.ts): Action/tool definitions and schemas bound to mineflayer skills.

Event Flow Example

Scenario: "Build a house"

Player: "build a house"
  ↓
[Perception] Event detected
  ↓
[Conscious] Architect plans the structure
  ↓
[Action] Executor takes the plan and manages the construction loop:
    - Step 1: Collect wood (calls ActionRegistry tool)
    - Step 2: Craft planks
    - Step 3: Build walls
  ↓
[Conscious] Brain confirms completion: "House is ready!"

Project Structure

src/
├── airi/                      # AIRI bridge, module shell, status publishing
├── cognitive/                  # 🧠 Perception → Reflex → Conscious → Action
│   ├── perception/            # Event definitions + rule evaluation
│   │   ├── events/
│   │   │   ├── index.ts
│   │   │   └── definitions/*
│   │   ├── rules/
│   │   │   ├── *.yaml
│   │   │   ├── engine.ts
│   │   │   ├── loader.ts
│   │   │   └── matcher.ts
│   │   └── pipeline.ts
│   ├── reflex/                # Fast, rule-based reactions
│   │   ├── reflex-manager.ts
│   │   ├── runtime.ts
│   │   ├── context.ts
│   │   └── behaviors/idle-gaze.ts
│   ├── conscious/             # LLM-powered reasoning
│   │   ├── brain.ts           # Core reasoning loop/orchestration
│   │   ├── js-planner.ts      # JS planning sandbox
│   │   ├── query-dsl.ts       # Read-only query runtime
│   │   ├── llm-log.ts         # Turn/log query helpers
│   │   ├── task-state.ts      # Task lifecycle enums/helpers
│   │   └── prompts/           # Prompt definitions (e.g., brain-prompt.ts)
│   ├── action/                # Task execution layer
│   │   ├── task-executor.ts   # Executes actions and emits lifecycle events
│   │   ├── action-registry.ts # Tool dispatch + schema validation
│   │   ├── llm-actions.ts     # Tool catalog
│   │   └── types.ts
│   ├── event-bus.ts           # Event bus core
│   ├── container.ts           # Dependency injection wiring
│   ├── index.ts               # Cognitive system entrypoint
│   └── types.ts               # Shared cognitive types
├── composables/
│   ├── config.ts              # Environment schema + defaults
│   ├── runtime-config.ts      # Persisted local runtime config
│   └── bot.ts
├── debug/                     # Debug dashboard, MCP REPL, viewer integration
├── libs/
│   └── mineflayer/           # Mineflayer bot wrapper/adapters
├── skills/                   # Atomic bot capabilities
├── plugins/                  # Mineflayer/bot plugins
├── utils/                    # Helpers
├── minecraft-bot-runtime.ts  # Bot lifecycle wrapper for reconnect/reconfigure
└── main.ts                   # Bot entrypoint

Design Principles

  1. Separation of Concerns: Each layer has a distinct responsibility
  2. Event-Driven: Loose coupling via centralized event system
  3. Inhibition Control: Reflexes prevent unnecessary LLM calls
  4. Extensibility: Easy to add new reflexes or conscious behaviors
  5. Cognitive Realism: Mimics human-like perception → reaction → deliberation

Future Enhancements

  • Perception Layer:

    • ⏱️ Temporal context window (remember recent events)
    • 🎯 Salience detection (filter noise, prioritize important events)
  • Reflex Layer:

    • 🏃 Dodge hostile mobs
    • 🛡️ Emergency combat responses
  • Conscious Layer:

    • 💭 Emotional state management
    • 🧠 Long-term memory integration
    • 🎭 Personality-driven responses

🛠️ Development

Commands

  • pnpm dev - Start the bot in development mode
  • pnpm lint - Run ESLint
  • pnpm typecheck - Run TypeScript type checking
  • pnpm test - Run tests

🙏 Acknowledgements

🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.