sync(ena-planner): align planner and outline with upstream
This commit is contained in:
@@ -7,6 +7,7 @@ import { extensionFolderPath } from '../../core/constants.js';
|
||||
import { EnaPlannerStorage } from '../../core/server-storage.js';
|
||||
import { postToIframe, isTrustedIframeEvent } from '../../core/iframe-messaging.js';
|
||||
import { DEFAULT_PROMPT_BLOCKS, BUILTIN_TEMPLATES } from './ena-planner-presets.js';
|
||||
import { formatOutlinePrompt } from '../story-outline/story-outline.js';
|
||||
|
||||
const EXT_NAME = 'ena-planner';
|
||||
const OVERLAY_ID = 'xiaobaix-ena-planner-overlay';
|
||||
@@ -307,7 +308,8 @@ function formatCharCardBlock(charObj) {
|
||||
function cleanAiMessageText(text) {
|
||||
let out = String(text ?? '');
|
||||
|
||||
// 1) Strip properly wrapped <think>/<thinking> blocks only.
|
||||
// 1) Strip everything before and including </think> (handles unclosed think blocks)
|
||||
out = out.replace(/^[\s\S]*?<\/think>/i, '');
|
||||
out = out.replace(/<think\b[^>]*>[\s\S]*?<\/think>/gi, '');
|
||||
out = out.replace(/<thinking\b[^>]*>[\s\S]*?<\/thinking>/gi, '');
|
||||
|
||||
@@ -688,19 +690,51 @@ async function buildWorldbookBlock(scanText) {
|
||||
* --------------------------
|
||||
*/
|
||||
function getChatVariables() {
|
||||
// Try multiple paths to get ST chat variables
|
||||
let vars = {};
|
||||
|
||||
// 1) Chat-level variables
|
||||
try {
|
||||
const ctx = getContextSafe();
|
||||
if (ctx?.chatMetadata?.variables) vars = { ...ctx.chatMetadata.variables };
|
||||
} catch {}
|
||||
if (!Object.keys(vars).length) {
|
||||
try {
|
||||
const ctx = getContextSafe();
|
||||
if (ctx?.chatMetadata?.variables) return ctx.chatMetadata.variables;
|
||||
} catch { }
|
||||
if (window.chat_metadata?.variables) vars = { ...window.chat_metadata.variables };
|
||||
} catch {}
|
||||
}
|
||||
if (!Object.keys(vars).length) {
|
||||
try {
|
||||
if (window.chat_metadata?.variables) return window.chat_metadata.variables;
|
||||
} catch { }
|
||||
try {
|
||||
const ctx = getContextSafe();
|
||||
if (ctx?.chat_metadata?.variables) return ctx.chat_metadata.variables;
|
||||
} catch { }
|
||||
return {};
|
||||
const ctx = getContextSafe();
|
||||
if (ctx?.chat_metadata?.variables) vars = { ...ctx.chat_metadata.variables };
|
||||
} catch {}
|
||||
}
|
||||
|
||||
// 2) Always merge message-level variables (some presets store vars here instead of chat-level)
|
||||
try {
|
||||
const msgVars = getLatestMessageVarTable();
|
||||
if (msgVars && typeof msgVars === 'object') {
|
||||
for (const key of Object.keys(msgVars)) {
|
||||
// Skip MVU internal metadata keys
|
||||
if (key === 'schema' || key === 'display_data' || key === 'delta_data') continue;
|
||||
if (vars[key] === undefined) {
|
||||
// Chat-level doesn't have this key at all — take from message-level
|
||||
vars[key] = msgVars[key];
|
||||
} else if (
|
||||
vars[key] && typeof vars[key] === 'object' && !Array.isArray(vars[key]) &&
|
||||
msgVars[key] && typeof msgVars[key] === 'object' && !Array.isArray(msgVars[key])
|
||||
) {
|
||||
// Both have this key as objects — shallow merge (message-level fills gaps)
|
||||
for (const subKey of Object.keys(msgVars[key])) {
|
||||
if (vars[key][subKey] === undefined) {
|
||||
vars[key][subKey] = msgVars[key][subKey];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch {}
|
||||
|
||||
return vars;
|
||||
}
|
||||
|
||||
function buildEjsContext() {
|
||||
@@ -735,6 +769,7 @@ function buildEjsContext() {
|
||||
|
||||
return {
|
||||
getvar, setvar,
|
||||
vars,
|
||||
Number, Math, JSON, String, Array, Object, parseInt, parseFloat,
|
||||
console: { log: () => { }, warn: () => { }, error: () => { } },
|
||||
};
|
||||
@@ -1101,6 +1136,7 @@ async function buildPlannerMessages(rawUserInput) {
|
||||
const scanText = [charBlockRaw, cachedSummary, recentChatRaw, vectorRaw, plotsRaw, rawUserInput].join('\n\n');
|
||||
|
||||
const worldbookRaw = await buildWorldbookBlock(scanText);
|
||||
const outlineRaw = typeof formatOutlinePrompt === 'function' ? (formatOutlinePrompt() || '') : '';
|
||||
|
||||
// Render templates/macros
|
||||
const charBlock = await renderTemplateAll(charBlockRaw, env, messageVars);
|
||||
@@ -1110,6 +1146,7 @@ async function buildPlannerMessages(rawUserInput) {
|
||||
const storySummary = cachedSummary.trim().length > 30 ? await renderTemplateAll(cachedSummary, env, messageVars) : '';
|
||||
const worldbook = await renderTemplateAll(worldbookRaw, env, messageVars);
|
||||
const userInput = await renderTemplateAll(rawUserInput, env, messageVars);
|
||||
const storyOutline = outlineRaw.trim().length > 10 ? await renderTemplateAll(outlineRaw, env, messageVars) : '';
|
||||
|
||||
const messages = [];
|
||||
|
||||
@@ -1125,6 +1162,11 @@ async function buildPlannerMessages(rawUserInput) {
|
||||
// 3) Worldbook
|
||||
if (String(worldbook).trim()) messages.push({ role: 'system', content: worldbook });
|
||||
|
||||
// 3.5) Story Outline / 剧情地图(小白板世界架构)
|
||||
if (storyOutline.trim()) {
|
||||
messages.push({ role: 'system', content: `<plot_map>\n${storyOutline}\n</plot_map>` });
|
||||
}
|
||||
|
||||
// 4) Chat history (last 2 AI responses — floors N-1 & N-3)
|
||||
if (String(recentChat).trim()) messages.push({ role: 'system', content: recentChat });
|
||||
|
||||
|
||||
Reference in New Issue
Block a user