feat: session auto-capture + NPC→Initiative push + lore grounding everywhere
CI / frontend (push) Successful in 31s
CI / rust (push) Successful in 6m3s

- SessionLogger listens for a new LogEntry bus event; dice rolls,
  initiative turns/rounds, generated encounters and calendar day
  advances land in the active session as timestamped entries — the
  raw material the AI summary actually needs. Mute toggle in the
  toolbar (persisted, default on).
- NPC Generator: '⚔ to initiative' button pushes the generated stat
  block (HP) into the tracker via the existing AddCombatants bus event.
- ragQuery now set on Encounter, Quest and Session summary too
  (NPC/Item/World already had it) — every generator is world-grounded.
This commit is contained in:
itsamejms
2026-09-07 10:25:38 +01:00
parent bbd492fff1
commit 3c599553fc
8 changed files with 89 additions and 7 deletions
+6
View File
@@ -205,6 +205,7 @@ IMPORTANT: Return ONLY a raw JSON object. NO markdown fences, NO code blocks, NO
system: "You are a D&D encounter designer. You MUST respond with ONLY valid JSON. No markdown fences, no code blocks, no explanation. Just the JSON object.",
temperature: 0.9,
max_tokens: 400,
ragQuery: `${terrain} monsters encounter`,
},
});
const parsed = parseLlmJson<Encounter>(result);
@@ -219,6 +220,11 @@ IMPORTANT: Return ONLY a raw JSON object. NO markdown fences, NO code blocks, NO
`Encounter: ${parsed.difficulty || "?"} in ${terrain}`,
`Encounter (party of ${partySize} level-${partyLevel}) in ${terrain}. ${monsters}\nTerrain: ${flattenValue(parsed.terrain)}\nDifficulty: ${flattenValue(parsed.difficulty)}\nLoot: ${flattenValue(parsed.loot)}`,
);
// ponytail: the fight starts — tell the session log.
bus.emit(Events.LogEntry, {
text: `⚔ Encounter: ${title} (${flattenValue(parsed.difficulty) || "?"}) — ${monsters}`,
tag: "#combat",
});
} else {
addToast("LLM returned an unparseable response", "error");
}