feat(ena-planner): make preserved response tags configurable with UI validation

This commit is contained in:
2026-02-25 22:23:19 +08:00
parent ad825c1189
commit b92d3bce28
2 changed files with 47 additions and 4 deletions

View File

@@ -32,6 +32,8 @@ function getDefaultSettings() {
// Plot extraction
plotCount: 2,
// Planner response tags to keep, in source order (empty = keep full response)
responseKeepTags: ['plot', 'note'],
// Planner prompts (designer)
promptBlocks: structuredClone(DEFAULT_PROMPT_BLOCKS),
@@ -100,6 +102,8 @@ function ensureSettings() {
}
}
deepMerge(s, d);
if (!Array.isArray(s.responseKeepTags)) s.responseKeepTags = structuredClone(d.responseKeepTags);
else s.responseKeepTags = normalizeResponseKeepTags(s.responseKeepTags);
// Migration: remove old keys that are no longer needed
delete s.includeCharacterLorebooks;
@@ -114,6 +118,20 @@ function ensureSettings() {
return s;
}
function normalizeResponseKeepTags(tags) {
const src = Array.isArray(tags) ? tags : [];
const cleaned = [];
for (const raw of src) {
const t = String(raw || '')
.trim()
.replace(/^<+|>+$/g, '')
.toLowerCase();
if (!/^[a-z][a-z0-9_-]*$/.test(t)) continue;
if (!cleaned.includes(t)) cleaned.push(t);
}
return cleaned;
}
async function loadConfig() {
const loaded = await EnaPlannerStorage.get('config', null);
config = (loaded && typeof loaded === 'object') ? loaded : getDefaultSettings();
@@ -878,10 +896,13 @@ function stripThinkBlocks(text) {
return out.trim();
}
function extractPlotAndNoteInOrder(text) {
function extractSelectedBlocksInOrder(text, tagNames) {
const names = normalizeResponseKeepTags(tagNames);
if (!Array.isArray(names) || names.length === 0) return '';
const src = String(text ?? '');
const blocks = [];
const re = /<(plot|note)\b[^>]*>[\s\S]*?<\/\1>/gi;
const escapedNames = names.map(n => n.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'));
const re = new RegExp(`<(${escapedNames.join('|')})\\b[^>]*>[\\s\\S]*?<\\/\\1>`, 'gi');
let m;
while ((m = re.exec(src)) !== null) {
blocks.push(m[0]);
@@ -891,8 +912,9 @@ function extractPlotAndNoteInOrder(text) {
function filterPlannerForInput(rawFull) {
const noThink = stripThinkBlocks(rawFull);
const onlyPN = extractPlotAndNoteInOrder(noThink);
if (onlyPN) return onlyPN;
const tags = ensureSettings().responseKeepTags;
const selected = extractSelectedBlocksInOrder(noThink, tags);
if (selected) return selected;
return noThink;
}