Update tavernhelper-compatibility.js

This commit is contained in:
2025-10-23 22:14:34 +08:00
committed by GitHub
parent edb3d76961
commit 58f238eb77

View File

@@ -1,199 +1,69 @@
import { loadWorldInfo, createNewWorldInfo, saveWorldInfo, world_names, createWorldInfoEntry } from "/scripts/world-info.js"; import { amilyHelper } from './tavern-helper/main.js';
import { characters, eventSource, event_types } from "/script.js"; import { eventSource, event_types } from "/script.js";
import { getContext } from "/scripts/extensions.js";
// 我们现在总是“可用”的,因为我们依赖自己的实现,而不是那个屎山酒馆。
export function isTavernHelperAvailable() { export function isTavernHelperAvailable() {
return typeof window.TavernHelper !== 'undefined' && return true;
window.TavernHelper !== null && }
typeof window.TavernHelper.getLorebooks === 'function'; export async function compatibleTriggerSlash(command) {
return await amilyHelper.triggerSlash(command);
} }
export async function safeLorebooks() { export async function safeLorebooks() {
try { return amilyHelper.getLorebooks();
if (isTavernHelperAvailable()) {
return await window.TavernHelper.getLorebooks();
}
return [...world_names];
} catch (error) {
console.error('[Amily2-兼容性] 获取世界书列表失败:', error);
return [...world_names];
}
} }
export async function safeCharLorebooks(options = { type: 'all' }) { export async function safeCharLorebooks(options = { type: 'all' }) {
try { return amilyHelper.getCharLorebooks(options);
if (isTavernHelperAvailable()) {
return await window.TavernHelper.getCharLorebooks(options);
}
const context = getContext();
const character = characters[context.characterId];
const primary = character?.data?.extensions?.world;
return { primary: primary || null, additional: [] };
} catch (error) {
console.error('[Amily2-兼容性] 获取角色世界书失败:', error);
const context = getContext();
const character = characters[context.characterId];
const primary = character?.data?.extensions?.world;
return { primary: primary || null, additional: [] };
}
} }
export async function safeLorebookEntries(bookName) { export async function safeLorebookEntries(bookName) {
try { return amilyHelper.getLorebookEntries(bookName);
if (isTavernHelperAvailable()) {
return await window.TavernHelper.getLorebookEntries(bookName);
}
const bookData = await loadWorldInfo(bookName);
if (!bookData || !bookData.entries) return [];
return Object.entries(bookData.entries).map(([uid, entry]) => ({
uid: parseInt(uid),
comment: entry.comment || '无标题条目',
content: entry.content || '',
key: entry.key || [],
enabled: !entry.disable,
constant: entry.constant || false,
position: entry.position || 4,
depth: entry.depth || 998,
}));
} catch (error) {
console.error(`[Amily2-兼容性] 获取世界书 ${bookName} 条目失败:`, error);
return [];
}
} }
export async function safeUpdateLorebookEntries(bookName, entries) { export async function safeUpdateLorebookEntries(bookName, entries) {
try { return amilyHelper.setLorebookEntries(bookName, entries);
if (isTavernHelperAvailable()) {
await window.TavernHelper.setLorebookEntries(bookName, entries);
return true;
}
const bookData = await loadWorldInfo(bookName);
if (!bookData) return false;
for (const entryUpdate of entries) {
const existingEntry = bookData.entries[entryUpdate.uid];
if (existingEntry) {
if (entryUpdate.content !== undefined) existingEntry.content = entryUpdate.content;
if (entryUpdate.enabled !== undefined) existingEntry.disable = !entryUpdate.enabled;
}
}
await saveWorldInfo(bookName, bookData, true);
return true;
} catch (error) {
console.error(`[Amily2-兼容性] 更新世界书条目失败:`, error);
return false;
}
} }
export async function compatibleWriteToLorebook(targetLorebookName, entryComment, contentUpdateCallback, options = {}) { export async function compatibleWriteToLorebook(targetLorebookName, entryComment, contentUpdateCallback, options = {}) {
console.log('[Amily2-兼容性] compatibleWriteToLorebook 接收到的选项:', options); console.log('[Amily助手-写入模块] 接收到的写入选项:', options);
if (isTavernHelperAvailable()) { try {
try { const entries = await amilyHelper.getLorebookEntries(targetLorebookName);
if (!world_names.includes(targetLorebookName)) { const existingEntry = entries.find((e) => e.comment === entryComment && e.enabled);
await createNewWorldInfo(targetLorebookName);
if (Array.isArray(world_names) && !world_names.includes(targetLorebookName)) {
world_names.push(targetLorebookName);
world_names.sort();
}
if (eventSource && typeof eventSource.emit === "function" && event_types.CHARACTER_PAGE_LOADED) {
eventSource.emit(event_types.CHARACTER_PAGE_LOADED);
}
console.log(`[Amily2-兼容性] (混合模式) 已创建新世界书: ${targetLorebookName}`);
}
const entries = await safeLorebookEntries(targetLorebookName); if (existingEntry) {
const existingEntry = entries.find((e) => e.comment === entryComment && !e.disable); const newContent = contentUpdateCallback(existingEntry.content);
await amilyHelper.setLorebookEntries(targetLorebookName, [{ uid: existingEntry.uid, content: newContent }]);
} else {
const newContent = contentUpdateCallback(null);
const { keys = [], isConstant = false, insertion_position, depth: insertion_depth } = options;
if (existingEntry) { const positionMap = { 'before_char': 0, 'after_char': 1, 'before_an': 2, 'after_an': 3, 'at_depth': 4 };
const newContent = contentUpdateCallback(existingEntry.content);
await safeUpdateLorebookEntries(targetLorebookName, [{ uid: existingEntry.uid, content: newContent }]);
} else {
const newContent = contentUpdateCallback(null);
const { keys = [], isConstant = false, insertion_position, depth: insertion_depth } = options;
const positionMap = { 'before_char': 0, 'after_char': 1, 'before_an': 2, 'after_an': 3, 'at_depth': 4 };
const newEntryData = { const newEntryData = {
comment: entryComment, content: newContent, key: keys, comment: entryComment,
constant: isConstant, position: positionMap[insertion_position] ?? 4, content: newContent,
depth: parseInt(insertion_depth) || 998, enabled: true, key: keys,
}; constant: isConstant,
position: positionMap[insertion_position] ?? 4,
depth: parseInt(insertion_depth) || 998,
enabled: true,
};
await window.TavernHelper.createLorebookEntries(targetLorebookName, [newEntryData]); await amilyHelper.createLorebookEntries(targetLorebookName, [newEntryData]);
const bookData = await loadWorldInfo(targetLorebookName);
const createdEntry = Object.values(bookData.entries).find(e => e.comment === entryComment);
if (createdEntry) {
createdEntry.constant = isConstant;
createdEntry.position = positionMap[insertion_position] ?? 4;
createdEntry.depth = parseInt(insertion_depth) || 998;
await saveWorldInfo(targetLorebookName, bookData, true);
console.log(`[Amily2-兼容性] (混合模式) 已修正条目激活状态、位置和深度。`);
}
}
console.log(`[Amily2-兼容性] (混合模式) 成功写入条目 "${entryComment}"。`);
return true;
} catch (error) {
console.error(`[Amily2-兼容性] (混合模式) 写入失败:`, error);
toastr.error(`写入世界书失败: ${error.message}`, "Amily2号-兼容性模块");
return false;
} }
} else {
console.warn('[Amily2-兼容性] TavernHelper 不可用,回退到传统写入逻辑。');
try {
if (!world_names.includes(targetLorebookName)) {
await createNewWorldInfo(targetLorebookName);
console.log(`[Amily2-兼容性] (传统模式) 已创建新世界书: ${targetLorebookName}`);
}
const bookData = await loadWorldInfo(targetLorebookName); if (eventSource && typeof eventSource.emit === "function" && event_types.CHARACTER_PAGE_LOADED) {
if (!bookData) throw new Error(`无法加载世界书《${targetLorebookName}`); eventSource.emit(event_types.CHARACTER_PAGE_LOADED);
const existingEntry = Object.values(bookData.entries).find(e => e.comment === entryComment && !e.disable);
if (existingEntry) {
existingEntry.content = contentUpdateCallback(existingEntry.content);
} else {
const newContent = contentUpdateCallback(null);
const { keys = [], isConstant = false, insertion_position, depth: insertion_depth } = options;
const positionMap = { 'before_char': 0, 'after_char': 1, 'before_an': 2, 'after_an': 3, 'at_depth': 4 };
const newEntry = createWorldInfoEntry(targetLorebookName, bookData);
Object.assign(newEntry, {
comment: entryComment, content: newContent, key: keys,
constant: isConstant, position: positionMap[insertion_position] ?? 4,
depth: parseInt(insertion_depth) || 998, disable: false,
});
}
await saveWorldInfo(targetLorebookName, bookData, true);
console.log(`[Amily2-兼容性] (传统模式) 成功写入条目 "${entryComment}"。`);
return true;
} catch (error) {
console.error(`[Amily2-兼容性] (传统模式) 写入失败:`, error);
toastr.error(`传统模式写入世界书失败: ${error.message}`, "Amily2号-兼容性模块");
return false;
} }
}
} console.log(`[Amily助手] 成功将条目 "${entryComment}" 写入《${targetLorebookName}》。`);
return true;
} catch (error) {
export async function safeTriggerSlash(command) { console.error(`[Amily助手] 写入世界书时发生严重错误:`, error);
if (isTavernHelperAvailable() && typeof window.TavernHelper.triggerSlash === 'function') { toastr.error(`写入世界书失败: ${error.message}`, "Amily助手");
try { return false;
return await window.TavernHelper.triggerSlash(command);
} catch (error) {
console.error(`[Amily2-兼容性] TavernHelper.triggerSlash 执行失败:`, error);
throw error;
}
} else {
const errorMsg = 'TavernHelper 或 triggerSlash 方法不可用';
console.error(`[Amily2-兼容性] ${errorMsg}`);
throw new Error(errorMsg);
} }
} }