Files
moeka-project/services
Zhou fanqi f6b53a37fa feat(minecraft): accurate perception, autonomic reflexes, and brain reliability (#1915)
## Summary

This PR upgrades the Minecraft bot's cognitive stack so it perceives
danger
accurately, reacts below the LLM brain with fast reflexes, and recovers
from
common brain failure modes. All changes are confined to
`services/minecraft/**`.

The desktop-side integration (spoken in-game chat, the online-gated
relay tool,
master binding in the UI) is submitted separately to keep this PR
focused; the
two are coupled only at runtime via AIRI context lanes, not at compile
time.

## What's included

**Perception — accurate damage attribution**
- `fall-tracker`: classify fall damage from physics-tick vertical
velocity.
- `attacker-tracker`: record the *real* attacker from the `entityHurt`
source,
  fixing "a mob shot me but I chased the player standing next to me".
- `low-health`: emit a danger signal at health ≤ 6 when no ready food is
held.
- `damage-taken`: resolve the source via a lava → drown → fire → fall →
  attacker chain and surface the attacker's name to the brain.

**Reflex — autonomic behaviors (run on the FSM tick, below the brain)**
- `defend`: auto-engage a hostile mob that attacks the bot/master and
hold the
  fight instead of thrashing (suppress damage wakes while attacking).
- `escape-hazard`: climb out of lava, or surface when drowning.
- `auto-eat`: eat ready food at health ≤ 6 (skipped during combat).
- A `reflexEngaged` autonomy flag suppresses auto-follow and auto-eat
while a
  defend/escape reflex owns the body.

**Conscious / skills — master recognition and reliability**
- Bind the "主人" role to the owner's in-game username so the bot
recognizes its
master in-world; enforce master-only command authority, never attack the
master, and react to a light hit with a short protest. Resolve players
by
  username, never the literal "player"/"主人".
- `js-planner`: strip prose-mixed LLM replies that caused `X is not
defined` and
give-up spirals; add a `botCall` sandbox bridge and the `whereName`
query
  chain method.
- Brain-prompt discipline: *saying is not doing*, *`recipePlan` is recon
not
crafting*, *eat only when food < 18* (regen is time-based), *defer equip
until
  a queued craft lands*.
- Skills: collect drops that spawn shortly after a kill (no more 0
loot);
`goToBed` skips occupied beds; detach auto-follow while
mining/collecting so
  digging is not interrupted.
- Platform: load perception rules on Windows (`fileURLToPath`); widen
the AIRI
  client read timeout to stop connection flapping.

The master username is injected via `generateBrainSystemPrompt(..., {
masterUsername })`
from config — it is **not** hardcoded.

## How tested

```bash
pnpm -F @proj-airi/minecraft-bot exec vitest run   # 220 tests; +56 new, all green
pnpm -F @proj-airi/minecraft-bot typecheck
pnpm exec moeru-lint services/minecraft            # 0 problems on changed files
```

- Each feature ships with unit tests (trackers, reflex behaviors,
planner
  salvage, skills, prompt, context service).
- Manual in-game testing: combat vs. pillagers/zombies, lava/water
escape,
low-health eating, crafting, master recognition with multiple players
present.

### Pre-existing baseline (not introduced by this PR)

Measured on `main` (`cb5c0783e`) before any change here:
- `tsc` reports 12 errors, all from a `vec3` 0.1.x/0.2.0
dependency-dedup
mismatch (`angleTo`) and `unknown[]` casts in `map-renderer.ts` /
`mcdata.ts` —
  files this PR does not touch. This PR adds **0** new type errors.
- 7 unit tests already fail on `main` (4 in `map-renderer.test.ts`, 2
timing-sensitive `brain.test.ts`, 1 timing-sensitive `rules.test.ts`).
This
  PR leaves those exactly as-is and does not touch those modules.

## Known limitations / follow-ups

- The `defend` reflex does not yet reliably engage ranged pillagers at
distance;
  the brain's `attack` tool currently covers that case.
- `craftRecipe` does not auto-unpack blocks (e.g. diamond_block →
diamond) or
  auto-gather missing intermediates for complex recipes.
- `inferDamageSource` orders environmental causes before
`recentAttacker`, which
  can mis-attribute an in-water-while-shot hit; low impact, deferred.
2026-06-05 11:51:18 +08:00
..