# Architettura ## Panoramica MUDlet AI Client usa un'architettura a 3 layer basata su Electron: ``` ┌─────────────────────────────────────────────────────────┐ │ ELECTRON MAIN │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────────┐ │ │ │ TelnetService│ │ OllamaService│ │ AutoplayerService│ │ │ └──────┬──────┘ └──────┬──────┘ └────────┬────────┘ │ │ │ │ │ │ │ └────────────────┼───────────────────┘ │ │ ▼ │ │ ┌─────────────────────┐ │ │ │ IPC Handlers │ │ │ └─────────┬───────────┘ │ └────────────────────────┼────────────────────────────────┘ │ ┌────────────────────────┼────────────────────────────────┐ │ PRELOAD JS │ │ contextBridge.exposeInMainWorld() │ └────────────────────────┼────────────────────────────────┘ │ ┌────────────────────────┼────────────────────────────────┐ │ REACT RENDERER │ │ ┌─────────┐ ┌─────────────┐ ┌─────────────────────┐ │ │ │ App │ │ GameWindow │ │ AutoplayerPanel │ │ │ └─────────┘ └─────────────┘ └─────────────────────┘ │ └─────────────────────────────────────────────────────────┘ ``` ## Layer 1: Electron Main Process ### Main Entry (`src/main/index.ts`) Responsabilità: - Inizializzazione finestra BrowserWindow - Setup IPC handlers - Event forwarding tra servizi e renderer - Lifecycle management (app ready, window closed, etc.) ```typescript // Flusso dati Telnet telnetService.on('output', (data) => { mainWindow.webContents.send('telnet-output', data); autoplayerService.processOutput(data); // Forward all'autoplayer }); ``` ### TelnetService (`src/main/services/TelnetService.ts`) Wrapper attorno a `telnet-client` con funzionalità aggiuntive: | Metodo | Descrizione | |--------|-------------| | `connect(host, port)` | Stabilisce connessione Telnet | | `send(data)` | Invia comando al server | | `getOutput()` | Restituisce buffer output | | `parseAnsiCodes(text)` | Converte ANSI escape codes in HTML | **Eventi:** - `output` - Emesso quando arrives nuovo output - `connected` - Connessione stabilita - `disconnected` - Connessione chiusa - `error` - Errore di connessione **Parsing ANSI:** ```typescript // ansicolor converte sequenze ANSI in spans colorati // Ogni span viene convertito in ``` ### OllamaService (`src/main/services/OllamaService.ts`) Client HTTP per Ollama API. Supporta: | Metodo | Descrizione | |--------|-------------| | `chat(messages, options)` | Chat singola, attesa risposta | | `chatStream(messages, options)` | Streaming response token-by-token | | `getLocalModels()` | Lista modelli disponibili | | `isAvailable()` | Check server reachability | **API Endpoint:** ``` POST http://ollama.solarpi.net/api/chat { "model": "llama3.2", "messages": [...], "stream": true, "options": { "temperature": 0.7, "num_predict": 512 } } ``` ### AutoplayerService (`src/main/services/AutoplayerService.ts`) Decision engine che orchestrate il loop autoplayer: ``` ┌─────────────────────────────────────────────────────────┐ │ AUTOPLAYER LOOP │ │ │ │ 1. OBSERVE ← processOutput(output) │ │ 2. PARSE ← parseGameState() │ │ 3. THINK ← ollamaService.chat() │ │ 4. DECIDE ← extractAction() │ │ 5. ACT ← executeAction() / queueAction() │ │ │ └─────────────────────────────────────────────────────────┘ ``` **Configurazione:** ```typescript interface AutoplayerConfig { model: string; // Model LLM da usare systemPrompt: string; // Comportamento del bot temperature: number; // Creatività (0.0-1.0) autoSend: boolean; // Auto-esegui azioni } ``` **Game State Parser:** ```typescript parseGameState(output: string): GameState { // Estrae: location, exits, players, objects, description } ``` **Decision Prompt:** ``` Context: [ultimi 30 righe output] Sei in: [location] Uscite disponibili: north, south, east Cosa fai? (rispondi SOLO con il comando) ``` ## Layer 2: Preload Script espone API sicure al renderer tramite `contextBridge`: ```javascript // Telnet telnetConnect(host, port) telnetSend(data) onTelnetOutput(callback) // Ollama ollamaChat(messages, options) ollamaGetModels() ollamaIsAvailable() // Autoplayer autoplayerConfigure(config) autoplayerStart() autoplayerStop() autoplayerExecuteAction(action) onAutoplayerDecision(callback) onAutoplayerAction(callback) ``` ## Layer 3: React Renderer ### App (`src/renderer/App.tsx`) Root component con navigation: ```typescript // Navigation state const [activePanel, setActivePanel] = useState<'connection' | 'game' | 'autoplayer'>(); // Connection status const [isConnected, setIsConnected] = useState(false); ``` ### GameWindow (`src/renderer/components/GameWindow.tsx`) Display principale del gioco: | Componente | Funzione | |------------|----------| | Output div | Visualizza output HTML con colors | | Form | Input comandi + submit | | Auto-scroll | Mantiene focus su output recente | ```typescript // Subscribe a output Telnet useEffect(() => { window.electronAPI.onTelnetOutput((data) => { setOutput(prev => prev + data); }); }, []); ``` ### AutoplayerPanel (`src/renderer/components/AutoplayerPanel.tsx`) Pannello controllo autoplayer: | Feature | UI | |---------|-----| | Toggle On/Off | Switch button | | Model selection | Dropdown (da Ollama) | | System prompt | Textarea modificabile | | Live status | Ultime decisioni/azioni | | Ollama availability | Check automatico | ## Flusso Dati ### Telnet → UI ``` 1. Telnet server → telnet-client 2. TelnetService → emits 'output' 3. Main process → ipcRenderer.send('telnet-output') 4. GameWindow → onTelnetOutput callback 5. React state → setOutput() 6. Render → HTML display ``` ### Autoplayer Decision ``` 1. Output Telnet arrives 2. AutoplayerService.processOutput() 3. parseGameState() → GameState { location, exits, ... } 4. shouldMakeDecision() → true/false 5. ollamaService.chat(messages) 6. extractAction() → "go north" 7. autoSend ? executeAction() : queueAction() 8. Events: 'decision', 'action' 9. UI updates: lastDecision, lastAction ``` ## Configurazione ### Environment - Server Ollama: `http://ollama.solarpi.net` (hardcoded) - LPMUD default: `172.24.19.225:6666` ### Tipi Condivisi ```typescript // src/main/services/AutoplayerService.ts interface GameState { location: string; description: string; exits: string[]; players: string[]; objects: string[]; health?: string; mana?: string; prompt?: string; } interface OllamaMessage { role: 'user' | 'assistant' | 'system'; content: string; } ``` ## Limitazioni Attuali | Componente | Limitation | Piani | |------------|------------|-------| | ANSI Parsing | Solo colori basic | Parser completo | | Game Parser | Regex-based, fragile | ML parser | | Autoplayer | No memory persistent | SQLite storage | | Mapper | Non implementato | Fase 3 | | Triggers | Non implementati | Fase 3 | | Plugins | Non implementati | Fase 4 |