Files
LoreMind/web/src/app/services/notebook-action.model.ts
IETM_FIXE\ietm6 6035df262d
All checks were successful
Build & Push Images / build (brain) (push) Successful in 1m32s
Build & Push Images / build (core) (push) Successful in 1m52s
Build & Push Images / build-switcher (push) Successful in 20s
Build & Push Images / build (web) (push) Successful in 1m48s
Ajout de la possibilité de faire des stats blocs pour tout ce qui est ennemis / créatures adverses.
Dorénavant, l'IA est capable de prendre en compte le format des quêtes, chapitres, Arc.... pour proposer des blocs plus complets.
Les ennemis sont également référençables directement dans la campagne.
Les références vers les ennemis dans la partie "donjon" est en cours d'ajout
2026-06-12 23:38:43 +02:00

77 lines
2.3 KiB
TypeScript

/**
* Protocole d'« actions » proposées par l'IA dans le chat d'un atelier : des blocs
* ```loremind-action {json} ``` que le front transforme en cartes « Créer dans la
* campagne ». Ce module définit les types + le parseur (extraction + texte nettoyé).
*/
export interface NotebookActionEntry {
minRoll: number;
maxRoll: number;
label: string;
detail?: string;
}
export interface NotebookAction {
type: 'npc' | 'scene' | 'chapter' | 'arc' | 'table';
name: string;
description?: string;
/** Legacy (anciens messages) : déroulé d'une scène → repli sur playerNarration. */
content?: string;
arcType?: 'LINEAR' | 'HUB';
diceFormula?: string;
entries?: NotebookActionEntry[];
// --- PNJ : valeurs des champs TEXT de la fiche (clés = template du système). ---
values?: Record<string, string>;
// --- Scène : champs narratifs enrichis (miroir de SceneCreate). ---
location?: string;
timing?: string;
atmosphere?: string;
playerNarration?: string;
gmSecretNotes?: string;
choicesConsequences?: string;
combatDifficulty?: string;
enemies?: string;
// --- Chapitre. ---
playerObjectives?: string;
narrativeStakes?: string;
// --- Chapitre + Arc. ---
gmNotes?: string;
// --- Arc. ---
themes?: string;
stakes?: string;
rewards?: string;
resolution?: string;
}
const ACTION_RE = /```loremind-action\s*([\s\S]*?)```/g;
const VALID_TYPES = new Set(['npc', 'scene', 'chapter', 'arc', 'table']);
/**
* Extrait les blocs d'action COMPLETS d'un message et renvoie le texte sans ces
* blocs. Les blocs encore en cours de streaming (clôture absente) ne matchent pas
* → ils restent affichés tels quels brièvement, puis deviennent une carte.
*/
export function parseNotebookActions(content: string): { text: string; actions: NotebookAction[] } {
const actions: NotebookAction[] = [];
if (!content) return { text: '', actions };
let match: RegExpExecArray | null;
ACTION_RE.lastIndex = 0;
while ((match = ACTION_RE.exec(content)) !== null) {
try {
const obj = JSON.parse(match[1].trim());
if (obj && typeof obj.type === 'string' && VALID_TYPES.has(obj.type) && typeof obj.name === 'string') {
actions.push(obj as NotebookAction);
}
} catch {
/* bloc JSON invalide : ignoré */
}
}
const text = content.replace(ACTION_RE, '').trim();
return { text, actions };
}