Fixed SD RPG

This commit is contained in:
2026-06-04 08:05:06 +03:00
parent d4cd8f02f4
commit 6189a5fb74
62 changed files with 6969 additions and 552 deletions
+78 -45
View File
@@ -1,4 +1,9 @@
import { setSessionId, setCurrentPersona, currentPersona, dom } from './state.js';
import {
setSessionId,
setCurrentPersona,
getNewChatDefaultPersona,
dom,
} from './state.js';
import {
initWizard,
GENRE_LABELS,
@@ -7,9 +12,9 @@ import {
fillGreetingSelect,
getSelectedGreeting,
} from './utils.js';
import { personaIndex, highlightPersona } from './personas.js';
import { personaIndex } from './personas.js';
let newChatPersonaId = currentPersona;
let newChatPersonaId = getNewChatDefaultPersona();
let newChatGreetingCtx = null;
const newChatGenres = new Set();
const newChatModalEl = document.getElementById('newChatModal');
@@ -84,7 +89,7 @@ function fillNewChatPersonaGrid() {
const grid = document.getElementById('newChatPersonaGrid');
if (!grid) return;
grid.innerHTML = '';
newChatPersonaId = currentPersona;
newChatPersonaId = getNewChatDefaultPersona();
for (const p of personaIndex.values()) {
const card = document.createElement('button');
card.type = 'button';
@@ -121,34 +126,8 @@ function updateNewChatGenresLabel() {
}
}
async function bootstrapRpg(sid, personaId, genreValue, settings) {
const { updateQuestPanel, addMessage } = await import('./chat.js');
await fetch(`/sessions/${sid}`, {
method: 'PATCH',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
rpg_enabled: true,
genre: genreValue,
rpg_settings_json: JSON.stringify(settings),
}),
});
const res = await fetch('/chat/rpg/bootstrap', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ session_id: sid, persona_id: personaId, genre: genreValue }),
});
if (res.ok) {
const data = await res.json();
if (data.quests) updateQuestPanel(data.quests);
if (data.plot_arc) {
const title = data.plot_arc.title || '';
const hint = data.plot_arc.next_beat_hint || '';
if (title || hint) addMessage('assistant', `📖 ${title}${hint ? '\n' + hint : ''}`);
}
}
}
export function openNewChatWizard() {
import('./personas.js').then(({ refreshPersonaBarHighlight }) => refreshPersonaBarHighlight());
fillNewChatPersonaGrid();
resetGenreGrid(document.getElementById('newChatGenreGrid'), newChatGenres);
updateNewChatGenresLabel();
@@ -161,8 +140,17 @@ export function openNewChatWizard() {
}
export async function createNewChatFromWizard() {
const { clearMessages, initChat, reloadChatFromServer } = await import('./chat.js');
const { loadSessions, applySessionUi } = await import('./sessions.js');
const {
clearMessages,
initChat,
reloadChatFromServer,
showImageGenerating,
removeImageGenerating,
updateQuestPanel,
updateAffinityDisplay,
renderChoices,
} = await import('./chat.js');
const { loadSessions, applySessionUi, renderSystemBlob } = await import('./sessions.js');
const sid = 'sess_' + Math.random().toString(36).slice(2, 10);
setSessionId(sid);
@@ -176,10 +164,23 @@ export async function createNewChatFromWizard() {
newChatWizard?.reset();
try {
const sessionPatch = { persona_id: newChatPersonaId, rpg_enabled: rpg };
if (rpg) {
sessionPatch.genre = [...newChatGenres].join(',') || 'adventure';
sessionPatch.rpg_settings_json = JSON.stringify({
dice: document.getElementById('ncSettingDice')?.checked ?? true,
narrator: document.getElementById('ncSettingNarrator')?.checked ?? true,
quests: document.getElementById('ncSettingQuests')?.checked ?? true,
affinity: document.getElementById('ncSettingAffinity')?.checked ?? true,
stats: document.getElementById('ncSettingStats')?.checked ?? false,
choices: document.getElementById('ncSettingChoices')?.checked ?? true,
});
}
await fetch(`/sessions/${sid}`, {
method: 'PATCH',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ persona_id: newChatPersonaId, rpg_enabled: rpg }),
body: JSON.stringify(sessionPatch),
});
if (customTitle) {
@@ -194,25 +195,57 @@ export async function createNewChatFromWizard() {
dom.headerTitle.textContent = rpg ? `${pName} — RPG` : `${pName} — новый чат`;
}
highlightPersona(newChatPersonaId);
const { highlightPersonaBar } = await import('./personas.js');
highlightPersonaBar(newChatPersonaId);
const greetingOverride = getNewChatFirstMesOverride();
await initChat(greetingOverride ? { first_mes_override: greetingOverride } : {});
if (rpg) {
const genreValue = [...newChatGenres].join(',') || 'adventure';
const settings = {
dice: document.getElementById('ncSettingDice')?.checked ?? true,
narrator: document.getElementById('ncSettingNarrator')?.checked ?? true,
quests: document.getElementById('ncSettingQuests')?.checked ?? true,
affinity: document.getElementById('ncSettingAffinity')?.checked ?? true,
choices: document.getElementById('ncSettingChoices')?.checked ?? true,
};
await bootstrapRpg(sid, newChatPersonaId, genreValue, settings);
const assistantWrapper = dom.messagesEl.querySelector('.message.assistant');
showImageGenerating(assistantWrapper);
let openingData = null;
try {
const openingRes = await fetch('/chat/opening/process', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
session_id: sid,
persona_id: newChatPersonaId,
rpg,
}),
});
openingData = await openingRes.json();
if (!openingRes.ok) {
console.error('opening/process failed:', openingData.detail || openingRes.statusText);
}
} finally {
removeImageGenerating(assistantWrapper);
}
await reloadChatFromServer(sid);
if (openingData?.quests?.length) {
updateQuestPanel(openingData.quests);
}
if (openingData?.affinity !== undefined) {
updateAffinityDisplay(openingData.affinity);
}
if (openingData?.image_error) {
const wrapper = dom.messagesEl.querySelector('.message.assistant');
if (wrapper) {
const err = document.createElement('div');
err.className = 'image-error';
err.textContent = '🖼 ' + openingData.image_error;
wrapper.appendChild(err);
}
}
const sessionRes = await fetch(`/sessions/${sid}`);
if (sessionRes.ok) applySessionUi(await sessionRes.json());
const blobRes = await fetch(`/chat/system/${sid}`);
if (blobRes.ok) renderSystemBlob(await blobRes.json());
await loadSessions();
} catch (e) {
console.error('createNewChat error:', e);