diff --git a/Assets/assistent.js b/Assets/assistent.js
index 37d6323..90e2219 100644
--- a/Assets/assistent.js
+++ b/Assets/assistent.js
@@ -87,6 +87,7 @@
inventoryFetchedAt: 0,
taste: { styles: [], likes: [], avoid: [], notes: '', updated: 0 },
streamEl: null,
+ streamMeta: null,
critiqueHopUsed: false,
visionHopUsed: false,
busyPhase: 'idle',
@@ -1981,7 +1982,60 @@
await sendChat({ fromAutoCritique: true, forceSlotIds: [GEN_ID] });
}
- function appendMessage(role, text, patch, civitaiResults) {
+ function currentPersonaInfo() {
+ const id = ($('sa_persona')?.value || localStorage.getItem(LS_PERSONA) || 'neutral').trim() || 'neutral';
+ const known = (state.personas || []).find((p) => p && p.id === id);
+ return {
+ id,
+ title: (known && known.title) || ({
+ neutral: 'Нейтральный',
+ lewd: 'Пошляк',
+ aggressive: 'Агрессивный',
+ }[id] || id),
+ };
+ }
+
+ function mountAssistantMeta(div, meta = {}) {
+ if (!div || div.querySelector('.sa-msg-meta')) {
+ return;
+ }
+ const persona = meta.persona || currentPersonaInfo();
+ const pack = meta.pack || $('sa_pack')?.value || '';
+ div.dataset.persona = persona.id || 'neutral';
+ if (pack) {
+ div.dataset.pack = pack;
+ }
+ const row = document.createElement('div');
+ row.className = 'sa-msg-meta';
+ const chip = document.createElement('span');
+ chip.className = `sa-persona-mark sa-persona-${persona.id || 'neutral'}`;
+ chip.textContent = persona.title || persona.id;
+ chip.title = `Характер: ${persona.title || persona.id}${pack ? ` · режим ${pack}` : ''}`;
+ row.appendChild(chip);
+ if (pack && pack !== 'write_prompt') {
+ const packEl = document.createElement('span');
+ packEl.className = 'sa-pack-mark';
+ packEl.textContent = pack.replace(/_/g, ' ');
+ packEl.title = `Режим: ${pack}`;
+ row.appendChild(packEl);
+ }
+ div.insertBefore(row, div.firstChild);
+ }
+
+ function setAssistantBody(div, text) {
+ if (!div) {
+ return;
+ }
+ let body = div.querySelector('.sa-msg-body');
+ if (!body) {
+ body = document.createElement('div');
+ body.className = 'sa-msg-body';
+ div.appendChild(body);
+ }
+ body.textContent = text || '';
+ }
+
+ function appendMessage(role, text, patch, civitaiResults, meta) {
const box = $('sa_messages');
if (!box) {
return null;
@@ -1989,9 +2043,16 @@
hideChatEmpty();
const div = document.createElement('div');
div.className = `sa-msg ${role}`;
+ if (role === 'assistant') {
+ mountAssistantMeta(div, meta);
+ }
const { prose, patch: extracted } = role === 'assistant' ? extractPatch(text) : { prose: text, patch: null };
const finalPatch = patch || extracted;
- div.textContent = prose || text || '';
+ if (role === 'assistant') {
+ setAssistantBody(div, prose || text || '');
+ } else {
+ div.textContent = prose || text || '';
+ }
if (finalPatch) {
const wrap = document.createElement('div');
wrap.className = 'sa-patch';
@@ -2009,7 +2070,7 @@
return div;
}
- function beginStreamMessage() {
+ function beginStreamMessage(meta) {
const box = $('sa_messages');
if (!box) {
return null;
@@ -2017,27 +2078,37 @@
hideChatEmpty();
const div = document.createElement('div');
div.className = 'sa-msg assistant sa-streaming sa-typing';
- div.innerHTML = 'Waiting for the model…';
+ mountAssistantMeta(div, meta);
+ const body = document.createElement('div');
+ body.className = 'sa-msg-body';
+ body.innerHTML = 'Waiting for the model…';
+ div.appendChild(body);
box.appendChild(div);
box.scrollTop = box.scrollHeight;
state.streamEl = div;
+ state.streamMeta = meta || null;
return div;
}
function appendStreamDelta(delta) {
if (!state.streamEl) {
- beginStreamMessage();
+ beginStreamMessage(state.streamMeta || undefined);
}
if (state.streamEl) {
if (state.streamEl.classList.contains('sa-typing')) {
state.streamEl.classList.remove('sa-typing');
- state.streamEl.textContent = '';
+ setAssistantBody(state.streamEl, '');
}
state.gotDelta = true;
if (state.busyPhase !== 'refining') {
setBusyPhase('streaming');
}
- state.streamEl.textContent += delta;
+ let body = state.streamEl.querySelector('.sa-msg-body');
+ if (!body) {
+ setAssistantBody(state.streamEl, '');
+ body = state.streamEl.querySelector('.sa-msg-body');
+ }
+ body.textContent += delta;
const box = $('sa_messages');
if (box) {
box.scrollTop = box.scrollHeight;
@@ -2047,14 +2118,18 @@
function finalizeStreamMessage(fullReply, civitaiResults) {
const el = state.streamEl;
+ const meta = state.streamMeta;
state.streamEl = null;
+ state.streamMeta = null;
if (!el) {
- appendMessage('assistant', fullReply, null, civitaiResults);
+ appendMessage('assistant', fullReply, null, civitaiResults, meta || undefined);
return;
}
el.classList.remove('sa-streaming', 'sa-typing');
+ mountAssistantMeta(el, meta || undefined);
const { prose, patch } = extractPatch(fullReply);
- el.textContent = prose || fullReply || '';
+ setAssistantBody(el, prose || fullReply || '');
+ el.querySelectorAll('.sa-patch, .sa-civitai-list').forEach((n) => n.remove());
if (patch) {
const wrap = document.createElement('div');
wrap.className = 'sa-patch';
@@ -3294,6 +3369,10 @@
}
}
+ const msgMeta = {
+ persona: currentPersonaInfo(),
+ pack,
+ };
state.history.push({ role: 'user', content: text });
appendMessage('user', text);
$('sa_input').value = '';
@@ -3346,7 +3425,7 @@
const finishOk = async (reply, civitaiResults) => {
state.busy = false;
setInterruptVisible(state.generating);
- state.history.push({ role: 'assistant', content: reply });
+ state.history.push({ role: 'assistant', content: reply, persona, pack });
stopBusyUi('Done');
await handleReplySideEffects(reply, civitaiResults, {
...opts,
@@ -3362,15 +3441,16 @@
if (state.streamEl) {
state.streamEl.classList.remove('sa-streaming', 'sa-typing');
state.streamEl.classList.add('error');
- state.streamEl.textContent = msg;
+ setAssistantBody(state.streamEl, msg);
state.streamEl = null;
+ state.streamMeta = null;
} else {
appendMessage('error', msg);
}
};
if (typeof makeWSRequest === 'function') {
- beginStreamMessage();
+ beginStreamMessage(msgMeta);
makeWSRequest(
'AssistentChatWS',
payload,
@@ -3390,7 +3470,8 @@
if (data.clear_stream) {
if (state.streamEl) {
state.streamEl.classList.add('sa-typing');
- state.streamEl.innerHTML = 'Refining…';
+ const body = state.streamEl.querySelector('.sa-msg-body') || state.streamEl;
+ body.innerHTML = 'Refining…';
}
setBusyPhase('refining');
return;
@@ -3400,7 +3481,7 @@
return;
}
if (data.done || data.reply != null) {
- const reply = data.reply || (state.streamEl && state.streamEl.textContent) || '';
+ const reply = data.reply || (state.streamEl?.querySelector('.sa-msg-body')?.textContent) || '';
const civitai = data.civitai_results || [];
finalizeStreamMessage(reply, civitai);
finishOk(reply, civitai);
@@ -3413,6 +3494,7 @@
if (state.streamEl) {
state.streamEl.remove();
state.streamEl = null;
+ state.streamMeta = null;
}
genericRequest(
'AssistentChat',
@@ -3423,7 +3505,7 @@
return;
}
const reply = data.reply || '';
- appendMessage('assistant', reply, null, data.civitai_results || []);
+ appendMessage('assistant', reply, null, data.civitai_results || [], msgMeta);
finishOk(reply, data.civitai_results || []);
},
0,
@@ -3443,7 +3525,7 @@
return;
}
const reply = data.reply || '';
- appendMessage('assistant', reply, null, data.civitai_results || []);
+ appendMessage('assistant', reply, null, data.civitai_results || [], msgMeta);
finishOk(reply, data.civitai_results || []);
},
0,