b3fac81c5a44ce67387c33de08bcf1db15061fe7
4
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
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> |
||
|
|
027ad7436f |
refactor(minecraft): restore services to neutral Minecraft semantics (#1950)
## Summary Restores `services/minecraft` to own **only Minecraft semantics**, decoupling the already-merged #1915 runtime contract from the (unmerged) #1916 desktop-relay design — as requested by @shinohara-rin in the #1916 review: > I'd prefer we first restore `services/minecraft` to only own Minecraft semantics, then reintroduce desktop relay/read-aloud through a generic module capability/tool contribution path or a Minecraft adapter. Otherwise `main` now contains half of a cross-PR runtime contract whose other half we are saying should not land as-is. The perception/reflex/brain reliability work from #1915 is untouched. This PR only removes the three desktop-coupling points baked into the bot service. ## Changes - **`airi-bridge.ts` — `handleActionIntent`**: a `spark:command` is high-level guidance from the AIRI server, now attributed to a neutral `'airi'` source. Removed the hardcoded `username = '主人'` / `relayedFrom: 'desktop-airi'` "treat it as if the master typed it in-game" framing. The generic server→bot directive still routes through `signal:chat_message` to trigger a fresh decision cycle, exactly as before — only the identity/provenance is neutralized. Binding a relayed command to the master's in-game identity is desktop-relay policy and will live in the Minecraft adapter. - **`minecraft-context-service.ts`**: stopped emitting the machine-readable `master:` status hint (whose only consumer was the desktop `gaming-minecraft` store) and removed the desktop-coupling NOTICE. The owner identity remains in the human-readable status **text** for the bot's own brain. - **`cognitive/index.ts`**: stopped forwarding the bot's own in-game chat over the `context:update` lane `minecraft:speech` (only meaningful with the #1916 desktop TTS consumer). The bot still ignores its own messages. ## How tested - Updated `minecraft-context-service.test.ts` to assert the neutral behavior (owner identity in status text, **never** as a `master:` hint). 2/2 pass. - `pnpm exec eslint <changed files>` → 0 problems. - The changed files typecheck clean. (Note: this worktree surfaces pre-existing `vec3@0.1.10` vs `vec3@0.2.0` dependency-resolution errors in unrelated files — `gaze.ts`/`runtime.ts`/`patched-goto.ts`/`world.ts`/`map-renderer`/`brain`/`rules` — present on `main` before this change too; not introduced here.) ## Follow-up Desktop relay (`relayToMinecraft`) and read-aloud will be reintroduced through a Minecraft adapter in the renderer (registering tools/prompts into the existing generic stores), so the runtime contract is owned by the Minecraft surface rather than baked into the neutral bot service. The generic stage-ui robustness fixes are already split out in #1949. --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Rin <shinohara-rin@users.noreply.github.com> |
||
|
|
39b68ddf12 |
fix(stage-ui): robust spark:command result + TTS session isolation (#1949)
## Summary Two small, generic robustness fixes, split out of the Minecraft desktop integration (#1916) so they can land independently of that rework — as suggested in @shinohara-rin's review: > The generic fixes in this PR, like the TTS session cleanup and `spark:command` result handling, seem separable and worth keeping in a smaller PR. Both are in shared `stage-ui` runtime code and contain **no Minecraft-specific logic**. ## What's included - **`spark:command` result handling** (`tools/character/orchestrator/spark-command.ts`): `command.destinations` may be `undefined` — the channel sender (`stores/llm.ts` `sendSparkCommand`) deletes it to broadcast to all authenticated peers. The success message's `.join()` therefore surfaced `Cannot read properties of undefined (reading 'join')` back to the LLM even though the send had already succeeded. Guard it and report a broadcast instead. - **TTS session isolation** (`components/scenes/Stage.vue` `openTtsSession`): a completing/erroring session now only clears the module-level `currentSession` if it **is** that session. The previous code cleared it whenever any `stream-` session completed, which becomes unsafe once sessions exist that are not assigned to `currentSession` (e.g. one-off read-aloud sessions) — one of those finishing would null a still-active chat session and drop the rest of the reply. ## How tested ```bash pnpm -F @proj-airi/stage-ui exec vitest run src/tools/character/orchestrator/spark-command.test.ts # 9 passed (+1 new) pnpm -F @proj-airi/stage-ui typecheck # 0 errors pnpm exec eslint <changed files> # 0 problems ``` - Regression test for the broadcast-destinations result message. ## Context This is the first, low-risk slice of reworking the Minecraft↔desktop integration around the neutral Context Flow architecture (per the #1916 review). The Minecraft relay/read-aloud behavior will be reintroduced through a Minecraft-owned adapter in a follow-up. --------- |
||
|
|
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.
|