v0.2.0 — M7: LLM Integration Frontend ↔ Backend

- api.js: API bridge to FastAPI backend
- Dynamic NPC dialogues via gemma4:12b (cached 30s)
- Periodic world event generation (every ~10s)
- Event validation (no soft-lock)
- Backend health check on startup
- Fallback to static dialogue if LLM offline
- Tested: events , dialogues 
This commit is contained in:
arch_agent
2026-07-17 20:24:58 +02:00
parent 5cf42a5e5d
commit face8023a4
5 changed files with 190 additions and 5 deletions
+89
View File
@@ -0,0 +1,89 @@
// api.js — Frontend ↔ Backend API Bridge
const API_BASE = 'http://localhost:8000/api';
class GameAPI {
constructor() {
this.cache = new Map();
this.cacheTimeout = 30000; // 30s cache for dialogues
}
async getPlayer() {
try {
const res = await fetch(`${API_BASE}/player`);
return await res.json();
} catch (e) {
console.warn('[API] getPlayer failed:', e);
return null;
}
}
async savePlayer(state) {
try {
await fetch(`${API_BASE}/player/save`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(state)
});
} catch (e) {
console.warn('[API] savePlayer failed:', e);
}
}
async getEvents(mapId) {
try {
const res = await fetch(`${API_BASE}/events/${mapId}`);
const data = await res.json();
return data.events || [];
} catch (e) {
console.warn('[API] getEvents failed:', e);
return [];
}
}
async generateEvent(mapId, playerLevel) {
try {
const res = await fetch(`${API_BASE}/llm/event?map_id=${mapId}&player_level=${playerLevel}`, {
method: 'POST'
});
const data = await res.json();
return data.event;
} catch (e) {
console.warn('[API] generateEvent failed:', e);
return null;
}
}
async getNPCDialogue(npcId, playerClass, playerLevel, mood) {
const cacheKey = `${npcId}_${mood}`;
if (this.cache.has(cacheKey)) {
const cached = this.cache.get(cacheKey);
if (Date.now() - cached.time < this.cacheTimeout) {
return cached.dialogue;
}
}
try {
const res = await fetch(`${API_BASE}/llm/dialogue?npc_id=${npcId}&player_class=${playerClass}&player_level=${playerLevel}&mood=${mood}`, {
method: 'POST'
});
const data = await res.json();
if (data.dialogue) {
this.cache.set(cacheKey, { dialogue: data.dialogue, time: Date.now() });
return data.dialogue;
}
} catch (e) {
console.warn('[API] getNPCDialogue failed:', e);
}
return null;
}
async health() {
try {
const res = await fetch(`${API_BASE}/health`);
return await res.json();
} catch (e) {
return { status: 'offline' };
}
}
}