mirror of
https://github.com/Wx-2025/ST-Amily2-Chat-Optimisation.git
synced 2026-06-07 13:15:51 +00:00
Update cwb_lorebookManager.js
This commit is contained in:
@@ -1,7 +1,15 @@
|
|||||||
import { state } from './cwb_state.js';
|
import { state } from './cwb_state.js';
|
||||||
import { logError, logDebug, showToastr, parseCustomFormat } from './cwb_utils.js';
|
import { logError, logDebug, showToastr, parseCustomFormat } from './cwb_utils.js';
|
||||||
|
import {
|
||||||
|
safeLorebooks,
|
||||||
|
safeCharLorebooks,
|
||||||
|
safeLorebookEntries,
|
||||||
|
safeUpdateLorebookEntries,
|
||||||
|
compatibleWriteToLorebook,
|
||||||
|
} from '../../core/tavernhelper-compatibility.js';
|
||||||
|
import { amilyHelper } from '../../core/tavern-helper/main.js';
|
||||||
|
|
||||||
const { SillyTavern, TavernHelper } = window;
|
const { SillyTavern } = window;
|
||||||
|
|
||||||
export async function getTargetWorldBook() {
|
export async function getTargetWorldBook() {
|
||||||
logDebug('[CWB-DIAGNOSTIC] getTargetWorldBook called. Current state:', {
|
logDebug('[CWB-DIAGNOSTIC] getTargetWorldBook called. Current state:', {
|
||||||
@@ -12,12 +20,8 @@ export async function getTargetWorldBook() {
|
|||||||
return state.customWorldBook;
|
return state.customWorldBook;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
let localTavernHelper = TavernHelper;
|
const charLorebooks = await safeCharLorebooks();
|
||||||
if (!localTavernHelper) {
|
const primaryBook = charLorebooks.primary;
|
||||||
// TavernHelper 未定义的情况下触发,但是为什么?
|
|
||||||
(localTavernHelper = window.TavernHelper);
|
|
||||||
}
|
|
||||||
const primaryBook = await localTavernHelper.getCurrentCharPrimaryLorebook();
|
|
||||||
if (!primaryBook) {
|
if (!primaryBook) {
|
||||||
showToastr('error', '当前角色未设置主世界书。');
|
showToastr('error', '当前角色未设置主世界书。');
|
||||||
return null;
|
return null;
|
||||||
@@ -40,7 +44,12 @@ export async function deleteLorebookEntries(uids) {
|
|||||||
const book = await getTargetWorldBook();
|
const book = await getTargetWorldBook();
|
||||||
if (!book) throw new Error('未找到目标世界书。');
|
if (!book) throw new Error('未找到目标世界书。');
|
||||||
|
|
||||||
await TavernHelper.deleteLorebookEntries(book, uids.map(Number));
|
const bookData = await amilyHelper.loadWorldInfo(book);
|
||||||
|
if (!bookData) throw new Error(`World book "${book}" not found.`);
|
||||||
|
uids.forEach(uid => {
|
||||||
|
delete bookData.entries[uid];
|
||||||
|
});
|
||||||
|
await amilyHelper.saveWorldInfo(book, bookData, true);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logError('删除世界书条目失败:', error);
|
logError('删除世界书条目失败:', error);
|
||||||
showToastr('error', `删除失败: ${error.message}`);
|
showToastr('error', `删除失败: ${error.message}`);
|
||||||
@@ -64,19 +73,14 @@ export async function saveDescriptionToLorebook(characterName, newDescription, s
|
|||||||
|
|
||||||
const newComment = `${safeCharName}-${chatIdentifier}`;
|
const newComment = `${safeCharName}-${chatIdentifier}`;
|
||||||
|
|
||||||
let bookName;
|
let bookName = await getTargetWorldBook();
|
||||||
if (state.worldbookTarget === 'custom' && state.customWorldBook) {
|
|
||||||
bookName = state.customWorldBook;
|
|
||||||
} else {
|
|
||||||
bookName = await TavernHelper.getCurrentCharPrimaryLorebook();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!bookName) {
|
if (!bookName) {
|
||||||
showToastr('error', '未能确定要写入的世界书。请检查主世界书或自定义世界书设置。');
|
showToastr('error', '未能确定要写入的世界书。请检查主世界书或自定义世界书设置。');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const entries = (await TavernHelper.getLorebookEntries(bookName)) || [];
|
const entries = (await safeLorebookEntries(bookName)) || [];
|
||||||
let existing = entries.find(e =>
|
let existing = entries.find(e =>
|
||||||
Array.isArray(e.keys) &&
|
Array.isArray(e.keys) &&
|
||||||
e.keys.includes(chatIdentifier) &&
|
e.keys.includes(chatIdentifier) &&
|
||||||
@@ -93,7 +97,7 @@ export async function saveDescriptionToLorebook(characterName, newDescription, s
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (existing) {
|
if (existing) {
|
||||||
await TavernHelper.setLorebookEntries(bookName, [{ uid: existing.uid, ...entryData }]);
|
await safeUpdateLorebookEntries(bookName, [{ uid: existing.uid, ...entryData }]);
|
||||||
} else {
|
} else {
|
||||||
const cwbEntries = entries.filter(e =>
|
const cwbEntries = entries.filter(e =>
|
||||||
Array.isArray(e.keys) &&
|
Array.isArray(e.keys) &&
|
||||||
@@ -131,7 +135,7 @@ export async function saveDescriptionToLorebook(characterName, newDescription, s
|
|||||||
order: newEntryData.order
|
order: newEntryData.order
|
||||||
});
|
});
|
||||||
|
|
||||||
await TavernHelper.createLorebookEntries(bookName, [newEntryData]);
|
await amilyHelper.createLorebookEntries(bookName, [newEntryData]);
|
||||||
}
|
}
|
||||||
showToastr('success', `角色 ${safeCharName} 的描述已保存到世界书。`);
|
showToastr('success', `角色 ${safeCharName} 的描述已保存到世界书。`);
|
||||||
return true;
|
return true;
|
||||||
@@ -169,19 +173,14 @@ export async function updateCharacterRosterLorebookEntry(processedCharacterNames
|
|||||||
|
|
||||||
const initialContentPrefix = `此为当前角色卡【${characterCardName}】中登场的角色,AI需要根据剧情让以下角色在合适的时机登场:\n\n`;
|
const initialContentPrefix = `此为当前角色卡【${characterCardName}】中登场的角色,AI需要根据剧情让以下角色在合适的时机登场:\n\n`;
|
||||||
|
|
||||||
let bookName;
|
let bookName = await getTargetWorldBook();
|
||||||
if (state.worldbookTarget === 'custom' && state.customWorldBook) {
|
|
||||||
bookName = state.customWorldBook;
|
|
||||||
} else {
|
|
||||||
bookName = await TavernHelper.getCurrentCharPrimaryLorebook();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!bookName) {
|
if (!bookName) {
|
||||||
showToastr('error', '未能确定要写入的世界书。请检查主世界书或自定义世界书设置。');
|
showToastr('error', '未能确定要写入的世界书。请检查主世界书或自定义世界书设置。');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let entries = (await TavernHelper.getLorebookEntries(bookName)) || [];
|
let entries = (await safeLorebookEntries(bookName)) || [];
|
||||||
let existingRosterEntry = entries.find(entry =>
|
let existingRosterEntry = entries.find(entry =>
|
||||||
entry.comment === rosterEntryComment ||
|
entry.comment === rosterEntryComment ||
|
||||||
entry.comment === `Amily2角色总集-${chatIdentifier}-角色总览`
|
entry.comment === `Amily2角色总集-${chatIdentifier}-角色总览`
|
||||||
@@ -244,11 +243,11 @@ export async function updateCharacterRosterLorebookEntry(processedCharacterNames
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (existingRosterEntry) {
|
if (existingRosterEntry) {
|
||||||
await TavernHelper.setLorebookEntries(bookName, [
|
await safeUpdateLorebookEntries(bookName, [
|
||||||
{ uid: existingRosterEntry.uid, comment: rosterEntryComment, ...entryData },
|
{ uid: existingRosterEntry.uid, comment: rosterEntryComment, ...entryData },
|
||||||
]);
|
]);
|
||||||
} else {
|
} else {
|
||||||
await TavernHelper.createLorebookEntries(bookName, [
|
await amilyHelper.createLorebookEntries(bookName, [
|
||||||
{ comment: rosterEntryComment, ...entryData },
|
{ comment: rosterEntryComment, ...entryData },
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
@@ -275,7 +274,7 @@ export async function manageAutoCardUpdateLorebookEntry() {
|
|||||||
const bookName = await getTargetWorldBook();
|
const bookName = await getTargetWorldBook();
|
||||||
if (!bookName) return;
|
if (!bookName) return;
|
||||||
|
|
||||||
const entries = (await TavernHelper.getLorebookEntries(bookName)) || [];
|
const entries = (await safeLorebookEntries(bookName)) || [];
|
||||||
|
|
||||||
const currentChatId = state.currentChatFileIdentifier;
|
const currentChatId = state.currentChatFileIdentifier;
|
||||||
if (!currentChatId || currentChatId.startsWith('unknown_chat')) {
|
if (!currentChatId || currentChatId.startsWith('unknown_chat')) {
|
||||||
@@ -304,7 +303,7 @@ export async function manageAutoCardUpdateLorebookEntry() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (entriesToUpdate.length > 0) {
|
if (entriesToUpdate.length > 0) {
|
||||||
await TavernHelper.setLorebookEntries(bookName, entriesToUpdate);
|
await safeUpdateLorebookEntries(bookName, entriesToUpdate);
|
||||||
logDebug(`已为聊天: ${cleanChatId} 管理了 ${entriesToUpdate.length} 个世界书条目的状态。`);
|
logDebug(`已为聊天: ${cleanChatId} 管理了 ${entriesToUpdate.length} 个世界书条目的状态。`);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -317,76 +316,3 @@ export async function manageAutoCardUpdateLorebookEntry() {
|
|||||||
logError('管理世界书条目时出错:', error);
|
logError('管理世界书条目时出错:', error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function syncNovelLorebookEntries(bookName, entries) {
|
|
||||||
if (!bookName || !Array.isArray(entries) || entries.length === 0) {
|
|
||||||
logError('[CWB-NovelSync] 参数无效或条目为空');
|
|
||||||
if (Array.isArray(entries) && entries.length === 0) {
|
|
||||||
showToastr('warning', '[小说处理] API回复中未找到有效条目。');
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const allEntries = (await TavernHelper.getLorebookEntries(bookName)) || [];
|
|
||||||
const managedEntries = allEntries.filter(e => e.comment?.startsWith(`[Amily2小说处理]`));
|
|
||||||
|
|
||||||
const entriesToUpdate = [];
|
|
||||||
const entriesToCreate = [];
|
|
||||||
let maxPart = 0;
|
|
||||||
managedEntries.forEach(entry => {
|
|
||||||
const match = entry.comment.match(/章节内容概述-第(\d+)部分/);
|
|
||||||
if (match && parseInt(match[1], 10) > maxPart) {
|
|
||||||
maxPart = parseInt(match[1], 10);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
let nextPart = maxPart + 1;
|
|
||||||
|
|
||||||
for (const entry of entries) {
|
|
||||||
const { title, content } = entry;
|
|
||||||
|
|
||||||
if (title === '章节内容概述') {
|
|
||||||
const loreData = {
|
|
||||||
keys: [`小说处理`, title, `第${nextPart}部分`],
|
|
||||||
content: content,
|
|
||||||
comment: `[Amily2小说处理] ${title}-第${nextPart}部分`,
|
|
||||||
enabled: true,
|
|
||||||
order: 100,
|
|
||||||
position: 'before_char',
|
|
||||||
};
|
|
||||||
entriesToCreate.push(loreData);
|
|
||||||
nextPart++;
|
|
||||||
} else {
|
|
||||||
const existingEntry = managedEntries.find(e => e.comment === `[Amily2小说处理] ${title}`);
|
|
||||||
|
|
||||||
const loreData = {
|
|
||||||
keys: [`小说处理`, title],
|
|
||||||
content: content,
|
|
||||||
comment: `[Amily2小说处理] ${title}`,
|
|
||||||
enabled: true,
|
|
||||||
order: 100,
|
|
||||||
position: 'before_char',
|
|
||||||
};
|
|
||||||
|
|
||||||
if (existingEntry) {
|
|
||||||
entriesToUpdate.push({ uid: existingEntry.uid, ...loreData });
|
|
||||||
} else {
|
|
||||||
entriesToCreate.push(loreData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (entriesToUpdate.length > 0) {
|
|
||||||
await TavernHelper.setLorebookEntries(bookName, entriesToUpdate);
|
|
||||||
showToastr('info', `[小说处理] 更新了 ${entriesToUpdate.length} 个世界书条目。`);
|
|
||||||
}
|
|
||||||
if (entriesToCreate.length > 0) {
|
|
||||||
await TavernHelper.createLorebookEntries(bookName, entriesToCreate);
|
|
||||||
showToastr('success', `[小说处理] 创建了 ${entriesToCreate.length} 个新世界书条目。`);
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
logError('同步小说世界书条目时出错:', error);
|
|
||||||
showToastr('error', '同步世界书失败,详情请查看控制台。');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user