mirror of
https://github.com/Wx-2025/ST-Amily2-Chat-Optimisation.git
synced 2026-06-06 20:55:51 +00:00
174 lines
7.6 KiB
JavaScript
174 lines
7.6 KiB
JavaScript
import {
|
||
world_names,
|
||
loadWorldInfo,
|
||
saveWorldInfo,
|
||
createNewWorldInfo,
|
||
createWorldInfoEntry,
|
||
reloadEditor
|
||
} from "/scripts/world-info.js";
|
||
import { characters, eventSource, event_types } from "/script.js";
|
||
import { getContext } from "/scripts/extensions.js";
|
||
import { executeSlashCommandsWithOptions } from '/scripts/slash-commands.js';
|
||
|
||
|
||
class AmilyHelper {
|
||
|
||
async getLorebooks() {
|
||
return [...world_names];
|
||
}
|
||
|
||
async getCharLorebooks(options = { type: 'all' }) {
|
||
try {
|
||
const context = getContext();
|
||
if (!context || !context.characterId) {
|
||
console.warn('[Amily助手] 无法获取当前角色上下文。');
|
||
return { primary: null, additional: [] };
|
||
}
|
||
const character = characters[context.characterId];
|
||
const primary = character?.data?.extensions?.world;
|
||
return { primary: primary || null, additional: [] };
|
||
} catch (error) {
|
||
console.error('[Amily助手] 获取角色世界书时出错:', error);
|
||
return { primary: null, additional: [] };
|
||
}
|
||
}
|
||
|
||
async getLorebookEntries(bookName) {
|
||
try {
|
||
const bookData = await loadWorldInfo(bookName);
|
||
if (!bookData || !bookData.entries) {
|
||
return [];
|
||
}
|
||
const positionMap = { 0: 'before_character_definition', 1: 'after_character_definition', 2: 'before_author_note', 3: 'after_author_note', 4: 'at_depth_as_system' };
|
||
return Object.entries(bookData.entries).map(([uid, entry]) => ({
|
||
uid: parseInt(uid),
|
||
comment: entry.comment || '无标题条目',
|
||
content: entry.content || '',
|
||
key: entry.key || [],
|
||
keys: entry.key || [],
|
||
enabled: !entry.disable,
|
||
constant: entry.constant || false,
|
||
position: positionMap[entry.position] || 'at_depth_as_system',
|
||
depth: entry.depth || 998,
|
||
}));
|
||
} catch (error) {
|
||
console.error(`[Amily助手] 获取世界书《${bookName}》条目时出错:`, error);
|
||
return [];
|
||
}
|
||
}
|
||
|
||
async setLorebookEntries(bookName, entries) {
|
||
try {
|
||
const bookData = await loadWorldInfo(bookName);
|
||
if (!bookData) {
|
||
console.error(`[Amily助手] 更新失败:找不到世界书《${bookName}》。`);
|
||
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;
|
||
if (entryUpdate.comment !== undefined) existingEntry.comment = entryUpdate.comment;
|
||
if (entryUpdate.key !== undefined) existingEntry.key = entryUpdate.key;
|
||
if (entryUpdate.keys !== undefined) existingEntry.key = entryUpdate.keys;
|
||
if (entryUpdate.constant !== undefined) existingEntry.constant = entryUpdate.constant;
|
||
if (entryUpdate.type === 'constant') existingEntry.constant = true;
|
||
if (entryUpdate.type === 'selective') existingEntry.constant = false;
|
||
if (entryUpdate.position !== undefined) {
|
||
const positionMap = { 'before_character_definition': 0, 'after_character_definition': 1, 'before_author_note': 2, 'after_author_note': 3, 'at_depth': 4, 'at_depth_as_system': 4 };
|
||
existingEntry.position = positionMap[entryUpdate.position] ?? 4;
|
||
}
|
||
if (entryUpdate.depth !== undefined) existingEntry.depth = entryUpdate.depth;
|
||
}
|
||
}
|
||
await saveWorldInfo(bookName, bookData, true);
|
||
reloadEditor(bookName); // 刷新编辑器
|
||
eventSource.emit(event_types.WORLD_INFO_UPDATED, bookName);
|
||
return true;
|
||
} catch (error) {
|
||
console.error(`[Amily助手] 更新世界书《${bookName}》条目时出错:`, error);
|
||
return false;
|
||
}
|
||
}
|
||
|
||
async createLorebookEntries(bookName, entries) {
|
||
try {
|
||
let bookData = await loadWorldInfo(bookName);
|
||
if (!bookData) {
|
||
console.warn(`[Amily助手] 世界书《${bookName}》不存在,将自动创建。`);
|
||
await this.createLorebook(bookName);
|
||
bookData = await loadWorldInfo(bookName);
|
||
if (!bookData) {
|
||
throw new Error(`创建并加载世界书《${bookName}》失败。`);
|
||
}
|
||
}
|
||
|
||
for (const newEntryData of entries) {
|
||
const newEntry = createWorldInfoEntry(bookName, bookData);
|
||
const positionMap = { 'before_character_definition': 0, 'after_character_definition': 1, 'before_author_note': 2, 'after_author_note': 3, 'at_depth': 4, 'at_depth_as_system': 4 };
|
||
Object.assign(newEntry, {
|
||
comment: newEntryData.comment || '新条目',
|
||
content: newEntryData.content || '',
|
||
key: newEntryData.keys || newEntryData.key || [],
|
||
constant: newEntryData.type === 'constant' ? true : (newEntryData.constant || false),
|
||
position: typeof newEntryData.position === 'string' ? (positionMap[newEntryData.position] ?? 4) : (newEntryData.position ?? 4),
|
||
depth: newEntryData.depth ?? 998,
|
||
disable: !(newEntryData.enabled ?? true),
|
||
});
|
||
if (newEntryData.type === 'selective') newEntry.constant = false;
|
||
}
|
||
await saveWorldInfo(bookName, bookData, true);
|
||
reloadEditor(bookName); // 刷新编辑器
|
||
return true;
|
||
} catch (error) {
|
||
console.error(`[Amily助手] 在世界书《${bookName}》中创建新条目时出错:`, error);
|
||
return false;
|
||
}
|
||
}
|
||
|
||
async createLorebook(bookName) {
|
||
try {
|
||
if (world_names.includes(bookName)) {
|
||
console.warn(`[Amily助手] 创建失败:世界书《${bookName}》已存在。`);
|
||
return false;
|
||
}
|
||
await createNewWorldInfo(bookName);
|
||
if (!world_names.includes(bookName)) {
|
||
world_names.push(bookName);
|
||
world_names.sort();
|
||
}
|
||
// 派发一个自定义事件,通知UI更新
|
||
document.dispatchEvent(new CustomEvent('amily-lorebook-created', { detail: { bookName } }));
|
||
return true;
|
||
} catch (error) {
|
||
console.error(`[Amily助手] 创建世界书《${bookName}》时出错:`, error);
|
||
return false;
|
||
}
|
||
}
|
||
|
||
async triggerSlash(command) {
|
||
try {
|
||
console.log(`[Amily助手] 正在执行斜杠命令: ${command}`);
|
||
const result = await executeSlashCommandsWithOptions(command);
|
||
if (result.isError) {
|
||
throw new Error(result.errorMessage);
|
||
}
|
||
return result.pipe;
|
||
} catch (error) {
|
||
console.error(`[Amily助手] 执行斜杠命令 '${command}' 时出错:`, error);
|
||
throw error;
|
||
}
|
||
}
|
||
|
||
async loadWorldInfo(bookName) {
|
||
return await loadWorldInfo(bookName);
|
||
}
|
||
|
||
async saveWorldInfo(bookName, data, isWorldInfo) {
|
||
await saveWorldInfo(bookName, data, isWorldInfo);
|
||
}
|
||
}
|
||
|
||
export const amilyHelper = new AmilyHelper();
|