reorganize: consolidate all documentation into readmes/
- Moved 20 root-level markdown files to readmes/ - Includes COMMANDS.md, CONFIG_README.md, all UNO docs, all completion reports - Added new: MEMORY_EDITOR_FEATURE.md, MEMORY_EDITOR_ESCAPING_FIX.md, CONFIG_SOURCES_ANALYSIS.md, MCP_TOOL_CALLING_ANALYSIS.md, and others - Root directory is now clean of documentation clutter
This commit is contained in:
574
readmes/UNO_FLOW_DIAGRAMS.md
Normal file
574
readmes/UNO_FLOW_DIAGRAMS.md
Normal file
@@ -0,0 +1,574 @@
|
||||
# 🎮 Miku UNO Bot - Visual Flow Diagrams
|
||||
|
||||
## High-Level Architecture
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Discord User │
|
||||
│ (Types: !uno create) │
|
||||
└──────────────────────────┬──────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Miku Discord Bot │
|
||||
│ (bot.py + commands) │
|
||||
│ │
|
||||
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
||||
│ │ bot.py │───▶│commands/uno.py│──▶│utils/uno_game│ │
|
||||
│ │ (!uno route) │ │ (cmd handler) │ │(MikuUnoPlayer│ │
|
||||
│ └──────────────┘ └──────────────┘ └───────┬────────┘ │
|
||||
│ │ │
|
||||
└──────────────────────────────────────────────────┼──────────┘
|
||||
│
|
||||
┌──────────────────────────────┼───────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌──────────────────┐ ┌─────────────┐ ┌─────────┐
|
||||
│ Playwright │ │ HTTP API │ │ LLM │
|
||||
│ (Browser Control)│ │ (Actions) │ │(Strategy│
|
||||
└────────┬─────────┘ └──────┬──────┘ └────┬────┘
|
||||
│ │ │
|
||||
│ │ │
|
||||
▼ ▼ │
|
||||
┌────────────────────────────────────────────┐ │
|
||||
│ UNO Game (Frontend) │ │
|
||||
│ http://192.168.1.2:3002 │ │
|
||||
│ │ │
|
||||
│ ┌──────────────────────────────────────┐ │ │
|
||||
│ │ React Components │ │ │
|
||||
│ │ - Game.js (main game logic) │ │ │
|
||||
│ │ - botActionExecutor.js │ │ │
|
||||
│ └──────────────┬───────────────────────┘ │ │
|
||||
│ │ │ │
|
||||
│ ▼ │ │
|
||||
│ ┌──────────────────────────────────────┐ │ │
|
||||
│ │ WebSocket Connection │ │ │
|
||||
│ └──────────────┬───────────────────────┘ │ │
|
||||
└─────────────────┼────────────────────────┘ │
|
||||
│ │
|
||||
▼ │
|
||||
┌────────────────────────────────────────────┐ │
|
||||
│ UNO Game (Backend) │ │
|
||||
│ http://localhost:5000 │ │
|
||||
│ │ │
|
||||
│ ┌──────────────────────────────────────┐ │ │
|
||||
│ │ Express Server │ │ │
|
||||
│ │ - WebSocket (Socket.IO) │ │ │
|
||||
│ │ - HTTP API endpoints │ │ │
|
||||
│ │ GET /api/game/:code/state ────┼─┼───┘
|
||||
│ │ POST /api/game/:code/action │ │
|
||||
│ └──────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────┐ │
|
||||
│ │ Game State Manager │ │
|
||||
│ │ - rooms{} dictionary │ │
|
||||
│ │ - player management │ │
|
||||
│ │ - turn logic │ │
|
||||
│ └──────────────────────────────────────┘ │
|
||||
└────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Command Flow: !uno create
|
||||
|
||||
```
|
||||
User Types: !uno create
|
||||
│
|
||||
▼
|
||||
┌─────────────────┐
|
||||
│ Discord.on() │
|
||||
│ message event │
|
||||
└────────┬────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────┐
|
||||
│ bot.py: Check if starts with !uno │
|
||||
└────────┬────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────────────────────────────────┐
|
||||
│ commands/uno.py: handle_uno_command() │
|
||||
│ Parse command: "create" │
|
||||
└────────┬───────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────────────────────────────────┐
|
||||
│ utils/uno_game.py: MikuUnoPlayer │
|
||||
│ player = MikuUnoPlayer(channel, user) │
|
||||
└────────┬───────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────────────────────────────────┐
|
||||
│ await player.create_and_join_game() │
|
||||
└────────┬───────────────────────────────┘
|
||||
│
|
||||
├─────────────────┐
|
||||
│ │
|
||||
▼ ▼
|
||||
┌──────────────┐ ┌───────────────────────┐
|
||||
│ Generate │ │ Launch Playwright │
|
||||
│ Room Code │ │ Headless Browser │
|
||||
│ (6 chars) │ │ (Chromium) │
|
||||
└──────┬───────┘ └───────┬───────────────┘
|
||||
│ │
|
||||
│ ▼
|
||||
│ ┌─────────────────────────┐
|
||||
│ │ Navigate to: │
|
||||
│ │ http://192.168.1.2:3002│
|
||||
│ └───────┬─────────────────┘
|
||||
│ │
|
||||
│ ▼
|
||||
│ ┌─────────────────────────┐
|
||||
│ │ Click "Join Room" │
|
||||
│ │ Enter room code │
|
||||
│ │ Submit │
|
||||
│ └───────┬─────────────────┘
|
||||
│ │
|
||||
▼ ▼
|
||||
┌──────────────────────────────────────┐
|
||||
│ Send Discord Embed: │
|
||||
│ "🎮 Created UNO room: ABC123 │
|
||||
│ Join at: http://192.168.1.2:3002 │
|
||||
│ I'm joining now as Player 2! ✨" │
|
||||
└──────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────────────────────────────┐
|
||||
│ Start game loop (play_game()) │
|
||||
│ Poll every 2 seconds │
|
||||
└──────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Game Loop Flow
|
||||
|
||||
```
|
||||
┌─────────────────────┐
|
||||
│ play_game() loop │
|
||||
│ while game_active │
|
||||
└──────────┬──────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────┐
|
||||
│ await asyncio.sleep(2) │ ◄─────┐
|
||||
└──────────┬──────────────────┘ │
|
||||
│ │
|
||||
▼ │
|
||||
┌─────────────────────────────┐ │
|
||||
│ get_game_state() │ │
|
||||
│ GET /api/game/:code/state │ │
|
||||
└──────────┬──────────────────┘ │
|
||||
│ │
|
||||
▼ │
|
||||
┌─────────────────────────────┐ │
|
||||
│ Is it Miku's turn? │ │
|
||||
│ (currentPlayer == "Player 2"?) │ │
|
||||
└──────┬────────────┬─────────┘ │
|
||||
│NO │YES │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ ┌─────────────────────┐ │
|
||||
│ │ get_miku_decision() │ │
|
||||
│ │ (Call LLM) │ │
|
||||
│ └──────┬──────────────┘ │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ ┌─────────────────────┐ │
|
||||
│ │ Build strategy prompt│ │
|
||||
│ │ - Current hand │ │
|
||||
│ │ - Top card │ │
|
||||
│ │ - Opponent cards │ │
|
||||
│ │ - Strategic tips │ │
|
||||
│ └──────┬──────────────┘ │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ ┌─────────────────────┐ │
|
||||
│ │ Query LLM │ │
|
||||
│ │ (utils.llm) │ │
|
||||
│ └──────┬──────────────┘ │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ ┌─────────────────────┐ │
|
||||
│ │ Parse JSON response │ │
|
||||
│ │ {"action": "play", │ │
|
||||
│ │ "card": "R5"} │ │
|
||||
│ └──────┬──────────────┘ │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ ┌─────────────────────┐ │
|
||||
│ │ Validate action │ │
|
||||
│ │ (is card in hand?) │ │
|
||||
│ └──────┬──────────────┘ │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ ┌─────────────────────┐ │
|
||||
│ │ send_action() │ │
|
||||
│ │ POST /api/game/... │ │
|
||||
│ └──────┬──────────────┘ │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ ┌─────────────────────┐ │
|
||||
│ │ send_trash_talk() │ │
|
||||
│ │ (Discord message) │ │
|
||||
│ └──────┬──────────────┘ │
|
||||
│ │ │
|
||||
└──────────┴───────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────┐
|
||||
│ Check if game ended │
|
||||
│ (winner exists?) │
|
||||
└──────┬───────────┬──────────┘
|
||||
│NO │YES
|
||||
│ │
|
||||
└───────────┤
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────┐
|
||||
│ Send final message │
|
||||
│ "Game ended! Winner: ..." │
|
||||
└──────────┬──────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────┐
|
||||
│ cleanup() │
|
||||
│ - Close browser │
|
||||
│ - Remove from active games │
|
||||
└─────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## LLM Strategy Decision Flow
|
||||
|
||||
```
|
||||
┌─────────────────────────────┐
|
||||
│ get_miku_decision() │
|
||||
└──────────┬──────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────┐
|
||||
│ build_strategy_prompt(game_state) │
|
||||
└──────────┬──────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────┐
|
||||
│ Construct prompt with: │
|
||||
│ "You are Miku, a cheerful idol..." │
|
||||
│ │
|
||||
│ Current Game State: │
|
||||
│ - Your hand: R5, G2, B7, WD4 │
|
||||
│ - Top card: Y3 │
|
||||
│ - Opponent has: 4 cards │
|
||||
│ │
|
||||
│ Strategic Tips: │
|
||||
│ - Match color or number │
|
||||
│ - Use Wild cards strategically │
|
||||
│ - Save action cards for impact │
|
||||
│ │
|
||||
│ Output ONLY valid JSON: │
|
||||
│ {"action":"play","card":"R5"} │
|
||||
└──────────┬──────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────┐
|
||||
│ await query_llama(prompt) │
|
||||
│ (utils.llm.query_llama) │
|
||||
└──────────┬──────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────┐
|
||||
│ LLM Response: │
|
||||
│ "{"action":"play","card":"Y5"}" │
|
||||
└──────────┬──────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────┐
|
||||
│ Try parse JSON │
|
||||
└──────┬───────────────┬──────────────────┘
|
||||
│ Success │ Fail
|
||||
│ │
|
||||
▼ ▼
|
||||
┌──────────────┐ ┌────────────────────┐
|
||||
│ Validate: │ │ Log error │
|
||||
│ - action OK? │ │ Fallback: draw │
|
||||
│ - card valid?│ └────────────────────┘
|
||||
│ - in hand? │
|
||||
└──────┬───────┘
|
||||
│ Valid
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────┐
|
||||
│ Return action dict │
|
||||
│ {"action":"play","card":..}│
|
||||
└─────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Trash Talk Selection Flow
|
||||
|
||||
```
|
||||
┌─────────────────────────────┐
|
||||
│ send_trash_talk(action) │
|
||||
└──────────┬──────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────┐
|
||||
│ Check card type │
|
||||
└──┬──┬──┬──┬──┬──────────────┘
|
||||
│ │ │ │ │
|
||||
│ │ │ │ └──────────┐
|
||||
│ │ │ └─────────┐ │
|
||||
│ │ └────────┐ │ │
|
||||
│ └───────┐ │ │ │
|
||||
▼ ▼ ▼ ▼ ▼
|
||||
┌──────┐ ┌────┐ ┌──┐ ┌──┐ ┌────┐
|
||||
│ WD4 │ │ D │ │S │ │W │ │REG │
|
||||
│Draw 4│ │Dr 2│ │Sk│ │Wi│ │Norm│
|
||||
└──┬───┘ └──┬─┘ └┬─┘ └┬─┘ └─┬──┘
|
||||
│ │ │ │ │
|
||||
▼ ▼ ▼ ▼ ▼
|
||||
┌────────────────────────────────────┐
|
||||
│ "Take four "Draw "Sorry~ │
|
||||
│ cards! 💙✨ two Skipping │
|
||||
│ I hope cards! your turn! │
|
||||
│ you're Don't Maybe next │
|
||||
│ ready for worry, time? 🎶" │
|
||||
│ a comeback~" I still │
|
||||
│ believe │
|
||||
│ in you~ │
|
||||
│ ✨" │
|
||||
└────────┬──────────────────────┬────┘
|
||||
│ │
|
||||
▼ ▼
|
||||
┌──────────────────┐ ┌───────────────┐
|
||||
│ Send to Discord │ │ Random choice │
|
||||
│ channel.send() │ │ from variants │
|
||||
└──────────────────┘ └───────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Data Flow: Game State
|
||||
|
||||
```
|
||||
┌────────────────────────────────────────┐
|
||||
│ UNO Backend (server.js) │
|
||||
│ │
|
||||
│ rooms = { │
|
||||
│ "ABC123": { │
|
||||
│ roomId: "ABC123", │
|
||||
│ users: ["Player 1", "Player 2"], │
|
||||
│ gameState: { │
|
||||
│ currentPlayer: "Player 2", │
|
||||
│ topCard: "Y3", │
|
||||
│ players: [ │
|
||||
│ { │
|
||||
│ name: "Player 1", │
|
||||
│ hand: [...], (hidden) │
|
||||
│ cardCount: 5 │
|
||||
│ }, │
|
||||
│ { │
|
||||
│ name: "Player 2", │
|
||||
│ hand: ["R5","G2",...], │
|
||||
│ cardCount: 7 │
|
||||
│ } │
|
||||
│ ], │
|
||||
│ winner: null, │
|
||||
│ direction: 1 │
|
||||
│ } │
|
||||
│ } │
|
||||
│ } │
|
||||
└─────────┬──────────────────────────────┘
|
||||
│
|
||||
│ HTTP GET /api/game/ABC123/state
|
||||
│
|
||||
▼
|
||||
┌────────────────────────────────────────┐
|
||||
│ JSON Response (filtered for Player 2) │
|
||||
│ { │
|
||||
│ "currentPlayer": "Player 2", │
|
||||
│ "topCard": "Y3", │
|
||||
│ "myHand": ["R5","G2","B7",...], │
|
||||
│ "myCardCount": 7, │
|
||||
│ "opponentCardCount": 5, │
|
||||
│ "direction": 1, │
|
||||
│ "winner": null │
|
||||
│ } │
|
||||
└─────────┬──────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌────────────────────────────────────────┐
|
||||
│ MikuUnoPlayer processes state │
|
||||
│ - Detects it's her turn │
|
||||
│ - Sees available cards │
|
||||
│ - Checks top card │
|
||||
│ - Asks LLM for strategy │
|
||||
└─────────┬──────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌────────────────────────────────────────┐
|
||||
│ LLM returns decision │
|
||||
│ {"action":"play","card":"R5"} │
|
||||
└─────────┬──────────────────────────────┘
|
||||
│
|
||||
│ HTTP POST /api/game/ABC123/action
|
||||
│ Body: {"action":"play","card":"R5"}
|
||||
│
|
||||
▼
|
||||
┌────────────────────────────────────────┐
|
||||
│ Backend validates and executes │
|
||||
│ - Check if R5 is in Player 2's hand │
|
||||
│ - Check if R5 can be played on Y3 │
|
||||
│ - Move R5 from hand to pile │
|
||||
│ - Update topCard to R5 │
|
||||
│ - Switch currentPlayer to Player 1 │
|
||||
│ - Emit WebSocket event to all clients │
|
||||
└────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌────────────────────────────────────────┐
|
||||
│ Frontend updates UI │
|
||||
│ - Card animation │
|
||||
│ - Update piles │
|
||||
│ - Show turn indicator │
|
||||
└────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## File Dependency Graph
|
||||
|
||||
```
|
||||
bot.py
|
||||
│
|
||||
├─> commands/uno.py
|
||||
│ │
|
||||
│ └─> utils/uno_game.py
|
||||
│ │
|
||||
│ ├─> playwright
|
||||
│ │ └─> (browser control)
|
||||
│ │
|
||||
│ ├─> utils/llm.py
|
||||
│ │ └─> query_llama()
|
||||
│ │
|
||||
│ ├─> aiohttp
|
||||
│ │ └─> (HTTP requests)
|
||||
│ │
|
||||
│ └─> discord.py
|
||||
│ └─> (Discord messages)
|
||||
│
|
||||
└─> globals.py
|
||||
└─> (configuration)
|
||||
|
||||
uno-online/
|
||||
│
|
||||
├─> server.js
|
||||
│ ├─> express
|
||||
│ ├─> socket.io (WebSocket)
|
||||
│ └─> HTTP API (/api/game/...)
|
||||
│
|
||||
└─> client/
|
||||
│
|
||||
├─> src/App.js
|
||||
│ └─> React Router
|
||||
│
|
||||
└─> src/components/Game.js
|
||||
├─> Socket.IO client
|
||||
└─> utils/botActionExecutor.js
|
||||
└─> (action validation & execution)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Discord Command Hierarchy
|
||||
|
||||
```
|
||||
!uno
|
||||
├─> create
|
||||
│ └─> MikuUnoPlayer.create_and_join_game()
|
||||
│ ├─> Generate room code
|
||||
│ ├─> Launch browser
|
||||
│ ├─> Join room
|
||||
│ └─> Start game loop
|
||||
│
|
||||
├─> join <code>
|
||||
│ └─> MikuUnoPlayer.join_game(code)
|
||||
│ ├─> Launch browser
|
||||
│ ├─> Join existing room
|
||||
│ └─> Start game loop
|
||||
│
|
||||
├─> list
|
||||
│ └─> Show active_uno_games dict
|
||||
│ └─> Format as Discord embed
|
||||
│
|
||||
├─> quit <code>
|
||||
│ └─> Find game by code
|
||||
│ ├─> Call cleanup()
|
||||
│ ├─> Remove from active_uno_games
|
||||
│ └─> Send confirmation
|
||||
│
|
||||
└─> help
|
||||
└─> Show command list
|
||||
└─> Format as Discord embed
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Timing Diagram
|
||||
|
||||
```
|
||||
Time User Bot UNO Server LLM
|
||||
─────────────────────────────────────────────────────────
|
||||
0s !uno create
|
||||
│
|
||||
1s ├─> Generate ABC123
|
||||
│
|
||||
2s ├─> Launch browser
|
||||
│
|
||||
3s ├─> Navigate to URL
|
||||
│
|
||||
4s ├─> Join room ──────> Create room
|
||||
│ Add Player 2
|
||||
5s ├─> Send embed
|
||||
Sees embed │ "Room: ABC123"
|
||||
│
|
||||
6s Opens URL │
|
||||
Joins room ─────────────────────> Add Player 1
|
||||
Start game
|
||||
Deal cards
|
||||
10s ├─> Poll state <──── Game state
|
||||
│ (Player 1 turn)
|
||||
│
|
||||
12s ├─> Poll state <──── Game state
|
||||
│ (Player 1 turn)
|
||||
│
|
||||
15s Plays card ─────────────────────> Update state
|
||||
Player 2 turn
|
||||
|
||||
16s ├─> Poll state <──── Game state
|
||||
│ (Player 2 turn!)
|
||||
│
|
||||
17s ├─> Strategy? ─────────────────> LLM
|
||||
│ │
|
||||
18s │ │ Think
|
||||
│ │
|
||||
19s │ <─────────────────── JSON ──┘
|
||||
│
|
||||
20s ├─> Play card ──────> Execute
|
||||
│ Validate
|
||||
│ Update
|
||||
21s ├─> Trash talk
|
||||
Sees message │ "Playing card~"
|
||||
│
|
||||
22s ├─> Poll state <──── Game state
|
||||
│ (Player 1 turn)
|
||||
... ... ...
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
These diagrams should help visualize how everything connects! 🎮✨
|
||||
Reference in New Issue
Block a user