feat(ia): add Judite & Narrador personas, per-player AI selection, persistent memory, and event reactivity

This commit is contained in:
Marcos Paulo
2026-08-18 19:00:11 -03:00
parent dafd96a4b6
commit ea55813019
13 changed files with 1036 additions and 88 deletions
+84
View File
@@ -0,0 +1,84 @@
# Plan: AI Multi-Personalities, Judite (SAC), Dynamic Tags, Persistent Memory & Event Expansion
## 1. Architecture & Component Design
```
┌───────────────────────────┐
│ CanalhandiaCommand │
│ (/ia, /iap, /ia persona) │
└─────────────┬─────────────┘
┌─────────────────┐ ┌──────────────┐ ┌────────────────────────┐
│ PlayerMemory │◄───────►│ Ai │◄───────►│ Tools / Wiki │
│ (ia-memoria.yml)│ │(Orchestrator)│ │ (lugares_jogador, etc.)│
└─────────────────┘ └──────┬───────┘ └────────────────────────┘
┌─────────────┴─────────────┐
│ MiniMax │
│ (HTTP / Tools / Chat) │
└───────────────────────────┘
```
### Components:
1. **`Persona.java` (Enum Enhancement):**
- Add `JUDITE` (SAC/Telemarketing persona) and `NARRADOR` (Fantasy narrator).
- Add `displayTag()` (e.g. "Judite", "Zoeiro", "Amigão") and `tagColor()` (Adventure `NamedTextColor`).
- Add persona-specific system prompts while maintaining the security invariant (`GUARD`).
2. **`PlayerMemory.java` (New Persistent Service):**
- Manages `plugins/Canalhandia/ia-memoria.yml`.
- Thread-safe, cached in-memory with disk persistence.
- Stores per-player:
- Selected persona (`judite`, `zoeiro`, etc.) or `null` (inherit server default).
- Persistent compressed summary of past conversations.
- List of key facts learned about the player (e.g., base coordinates, preferred building materials, fear of mobs).
- Provides sliding-window compression: auto-condenses turns when memory exceeds thresholds.
3. **`Tools.java` (Expanded Function Calling):**
- Add `lugares_jogador` function: fetches recent deaths from `DeathLog`, saved coordinates from `Notes`, and current biome/world.
- Update definitions JSON to make the tool discoverable to the LLM.
4. **`Ai.java` (Orchestrator Updates):**
- Integrate `PlayerMemory`.
- Resolve effective persona per player (`playerMemory.persona(player)` -> fallback `settings.aiPersona()`).
- In `compose()`: inject effective persona tone + `playerMemory.formatContext(player)` + location summary.
- In `deliver()` and `style()`: render dynamic tag `Msg.tag(persona.displayTag(), persona.tagColor())` instead of fixed `[IA]`.
- Update `saySomething()` to support persona-specific spontaneous events.
5. **`CanalhandiaCommand.java` (CLI & Interaction):**
- Enhance `/ia persona [nome]` to set per-player persona or list available personas with descriptions and click-to-select suggestions.
- Add `/ia persona padrao` to reset preference.
- Add `/ia status` and `/ia esquecer`.
6. **`Canalhandia.java` & Event Hooks (Event Expansion):**
- Wire expanded event triggers into `saySomething()`:
- Player joins (`aiWelcome`)
- Player death streaks / notable deaths (`onDeath`)
- Milestones & custom achievements (`onMilestone`)
- Raid and boss victories (`onBossDefeat`)
---
## 2. File Touches
1. `src/main/java/dev/marcospaulo/canalhandia/Persona.java` — Add `JUDITE`, `NARRADOR`, tags, colors, and prompts.
2. `src/main/java/dev/marcospaulo/canalhandia/PlayerMemory.java` — New class for persistent per-player memory & compression.
3. `src/main/java/dev/marcospaulo/canalhandia/Tools.java` — Add `lugares_jogador` tool and integration with `DeathLog` & `Notes`.
4. `src/main/java/dev/marcospaulo/canalhandia/Ai.java` — Integrate `PlayerMemory`, dynamic persona tags, prompt composition.
5. `src/main/java/dev/marcospaulo/canalhandia/CanalhandiaCommand.java` — Subcommands for `/ia persona`, `/ia status`, `/ia esquecer`.
6. `src/main/java/dev/marcospaulo/canalhandia/Canalhandia.java` — Wire `PlayerMemory` lifecycle, expand event hooks.
7. `src/test/java/dev/marcospaulo/canalhandia/PersonaTest.java` — Unit tests for personas, tags, and system prompts.
8. `src/test/java/dev/marcospaulo/canalhandia/PlayerMemoryTest.java` — Unit tests for YAML storage, compression, and per-player state.
9. `src/test/java/dev/marcospaulo/canalhandia/ToolsTest.java` — Unit tests for `lugares_jogador` and tool execution.
---
## 3. Risks & Mitigations
- **Risk:** Token context blowup from memory/chat history.
- *Mitigation:* Hard-cap memory summary length (max 300 chars) and max facts (max 5 items) per player.
- **Risk:** Thread safety when reading player memory in async AI tasks.
- *Mitigation:* Synchronize all `PlayerMemory` reads/writes under monitor; snapshot memory context as immutable strings on main thread before async dispatch.
- **Risk:** API costs from spontaneous event comments.
- *Mitigation:* All events remain strictly governed by `Budget` with cooldown windows and hourly/daily spend limits.
+103
View File
@@ -0,0 +1,103 @@
# Spec: AI Multi-Personalities, Judite (SAC), Dynamic Tags, Persistent Memory & Event Expansion
## 1. Objective & Motivation
Transform the `ia` module in the `Canalhandia` plugin into a rich, personalized companion system:
1. **Per-Player AI Selection:** Each player can pick their own AI persona (or use server default).
2. **Dynamic Chat Tags:** Replace static `[IA]` tag with the active persona's name (e.g. `[Judite]`, `[Zoeiro]`, `[Amigão]`, `[Seco]`, `[Aldeão]`, `[Narrador]`).
3. **Judite Roleplay Persona:** A hilarious Brazilian SAC/telemarketing attendant (Porta dos Fundos style) with fictitious protocols, bureaucratic quirks, hold music jokes, and deadpan efficiency.
4. **Persistent Compressed Memory (`ia-memoria.yml`):** Retain player memories, key facts, past locations, and sliding-window conversation summaries across server reboots.
5. **Rich Location & Stat Grounding:** Grant the AI direct knowledge of places the player has been (death locations via `DeathLog`, saved pins via `Notes`, current biomes/coords, statistics).
6. **Expanded Event Reactivity:** Broaden spontaneous AI commentary to include death streaks, boss/raid triumphs, milestone achievements, first-time dimension visits, and custom join greetings with persona-specific voice.
---
## 2. Personas Specification
### A. Tag & Persona Definitions
| Persona Key | Display Tag | Tone & Character Description |
|---|---|---|
| `judite` | `[Judite]` | Atendente de SAC/telemarketing burocrática e impaciente, viciada em gerundismo ("estaremos verificando no sistema"), gera números de protocolo ("Protocolo 2026-MC-..."), pede para aguardar na linha, cobra pendências (fome/vida baixa) com frieza corporativa e dá respostas precisas. |
| `zoeiro` | `[Zoeiro]` | Veterano debochado do servidor que usa mortes e estatísticas contra o jogador, mantendo o bom humor. |
| `amigao` | `[Amigão]` | Amigo paciente, caloroso e prestativo, ideal para acolher novatos sem sarcasmo. |
| `seco` | `[Seco]` | Minimalista, direto e sarcástico, 1 a 2 frases curtas sem emoção. |
| `aldeao` | `[Aldeão]` | Solene e místico, falando como um sábio aldeão ancestral de Minecraft. |
| `narrador` | `[Narrador]` | Narrador épico e dramático de RPG de fantasia medieval ("Eis que o bravo viajante indaga..."). |
| `neutro` | `[IA]` | Assistente direto, neutro e sem persona marcante. |
### B. Dynamic Tag Rendering
- In `/ia`, `/iap`, and chat responses: Tag is rendered as `Msg.tag(persona.displayTag(), persona.tagColor())` instead of fixed `[IA]`.
- Java players retain rich hover cards detailing the persona name and question prompt.
---
## 3. Player Preferences & Commands
- `/ia persona` / `/ia personalidade`: Lists all available personas and highlights the player's active selection.
- `/ia persona <nome>`: Sets the player's personal persona (persisted in `ia-memoria.yml`).
- `/ia persona padrao` / `/ia persona reset`: Resets to the server-wide default persona configured in `config.yml`.
- `/ia status`: Displays active persona, memory status, and summary of stored facts for the player.
- `/ia esquecer`: Clears the player's stored conversation memory/facts.
---
## 4. Persistent Memory & Chat Compression Engine (`PlayerMemory`)
### File: `plugins/Canalhandia/ia-memoria.yml`
```yaml
players:
<uuid>:
name: "Diguin_n"
persona: "judite"
updated_at: 1771450000000
summary: "Jogador explorou o Nether e perguntou sobre poções de agilidade. Tem base na vila das coordenadas 120, 64, -300."
facts:
- "Tem base na vila (120, 64, -300)"
- "Morreu recentemente no Void"
- "Gosta de criar axolotes e golfinhos"
```
### Memory Mechanics:
1. **Short-Term Session Memory:** Live exchanges stored in memory for immediate follow-ups.
2. **Key Facts Extraction / Journaling:** Maintained per player to keep long-term context across restarts.
3. **Sliding Compression:** When conversation turns exceed limits, compress previous interactions into the player's persistent summary string, ensuring bounded token usage.
---
## 5. Context Grounding & Tools
- **Tool `lugares_jogador`:**
- Retrieves player's recent deaths from `DeathLog` (`mortes.yml`).
- Retrieves player's saved pins/bases from `Notes` (`notas.yml`).
- Retrieves current coordinates, world dimension, and biome.
- **Tool `estatisticas_jogador`:**
- Reads mined blocks, mob kills, total deaths, playtime from `OfflineStats`.
- **Tool `conquistas_jogador`:**
- Reads unlocked titles and achievements.
- Server leaderboards, recent public milestones, online player list.
---
## 6. Expanded Event Engine
The AI can react to diverse gameplay triggers (gated by `aiBudget` and configurable settings):
1. **Death Streaks & Notable Deaths:** Void deaths, falling, explosions, Warden/Wither encounters.
2. **Player Joins (`aiWelcome`):** Persona greets returning player with contextual facts (e.g. Judite mentions pending tickets or absence duration).
3. **Milestone Crossings:** When a player crosses round milestones (e.g. 100km walked, 10,000 blocks mined) or earns rare achievements.
4. **Boss Defeats & Raids:** Dragon/Wither defeats or raid victories.
---
## 7. Acceptance Criteria
1. All existing 316 unit tests continue to pass without regressions.
2. New unit tests covering:
- `PersonaTest`: Validation of all personas including `JUDITE` and `NARRADOR`, display tags, system prompts, safety guard invariant.
- `PlayerMemoryTest`: YAML serialization, compression, fact storage, and per-player persona retention.
- `ToolsTest`: Verification of `lugares_jogador` and updated tool definitions.
- `AiTagTest`: Dynamic persona tag rendering in chat and hover styling.
- `EventTest`: Event triggers formatting prompts with appropriate persona context.
3. `/ia persona <nome>` persists choices across restarts.
4. Full clean compilation with `mvn test` and `mvn package`.
@@ -0,0 +1,46 @@
# Tasks: AI Multi-Personalities, Judite (SAC), Dynamic Tags, Persistent Memory & Event Expansion
- [x] **Task 1: Persona Enhancement (`Persona.java` & `PersonaTest.java`)**
- Add `JUDITE` (SAC/telemarketing attendant) and `NARRADOR` (fantasy narrator) to `Persona` enum.
- Add `displayTag()` (e.g. "Judite", "Zoeiro", "Amigão", "Seco", "Aldeão", "Narrador", "IA") and `tagColor()` (`NamedTextColor`).
- Add persona system prompts with safety guard invariant.
- Update `PersonaTest.java` to assert all enum keys, display tags, colors, and guard constraints.
- [x] **Task 2: Persistent Player Memory & Compression (`PlayerMemory.java` & `PlayerMemoryTest.java`)**
- Create `PlayerMemory.java` persisted at `plugins/Canalhandia/ia-memoria.yml`.
- Implement per-player persona setting (`getPersona`, `setPersona`, `resetPersona`).
- Implement turn recording with automatic sliding-window summary condensation.
- Implement key facts list per player (`addFact`, `getFacts`).
- Implement `formatContext(UUID player)` for AI system prompt formatting.
- Write comprehensive unit tests in `PlayerMemoryTest.java`.
- [x] **Task 3: Location Grounding Tool (`Tools.java` & `ToolsTest.java`)**
- Add `lugares_jogador` function definition to `Tools.DEFINITIONS`.
- Implement `lugares_jogador` in `Tools.java` pulling recent deaths from `DeathLog`, saved pins from `Notes`, and current world/biome.
- Write unit tests in `ToolsTest.java` verifying tool execution and response formatting.
- [x] **Task 4: AI Orchestration & Dynamic Tag Styling (`Ai.java`)**
- Integrate `PlayerMemory` into `Ai.java`.
- Resolve effective persona per player in `ask()`.
- Update `compose()` to inject player persona prompt, player memory context, and location context.
- Update `deliver()` and `style()` to display dynamic persona tag (e.g. `[Judite]`, `[Zoeiro]`) and hover metadata.
- Update `saySomething()` to support persona-specific spontaneous speech.
- [x] **Task 5: Command Interface & Subcommands (`CanalhandiaCommand.java`)**
- Implement `/ia persona` / `/ia personalidade` list and player preference switcher (`/ia persona <nome>`).
- Implement `/ia persona padrao` to reset preference.
- Implement `/ia status` to show active persona, memory summary, and facts.
- Implement `/ia esquecer` to clear personal memory.
- Update tab-completion for `/ia` with new subcommands and persona keys.
- [x] **Task 6: Event Expansion & Plugin Wiring (`Canalhandia.java`)**
- Initialize and expose `PlayerMemory` in `Canalhandia.java`.
- Expand event triggers in `Canalhandia.java`:
- Joins (`onJoinWelcome`) with persona-specific greeting.
- Notable deaths & streaks (`onPlayerDeath`) with persona-specific commentary.
- Milestone completions (`onMilestone`) with persona-specific recognition.
- [x] **Task 7: Verification & Build (`mvn test` & `mvn package`)**
- Run full test suite (`mvn test`) ensuring 100% pass rate.
- Package final jar (`mvn package`).
- Verify all acceptance criteria from `spec.md`.