feat: integrate host bridge prompt pipeline

This commit is contained in:
Youzini-afk
2026-03-26 22:24:45 +08:00
parent 0fcc50997e
commit 777edf9f9a
22 changed files with 2710 additions and 307 deletions

View File

@@ -3,6 +3,165 @@
import { getContext } from "../../../extensions.js";
function safeClone(value, fallback) {
if (value == null) {
return fallback;
}
try {
if (typeof structuredClone === "function") {
return structuredClone(value);
}
} catch {
// ignore and fall back to JSON clone
}
try {
return JSON.parse(JSON.stringify(value));
} catch {
return fallback ?? value;
}
}
function resolveCharacter(ctx) {
const charId = ctx?.characterId;
return (
ctx?.character ||
ctx?.characters?.[Number(charId)] ||
ctx?.characters?.[charId] ||
null
);
}
function resolvePersona(ctx) {
return (
ctx?.powerUserSettings?.persona_description ||
ctx?.extensionSettings?.persona_description ||
ctx?.name1_description ||
ctx?.persona ||
""
);
}
function resolveCharacterDescription(char) {
return (
char?.description ||
char?.data?.description ||
char?.data?.personality ||
""
);
}
function resolveLastUserMessage(chat = []) {
return (
chat.findLast?.((message) => message?.is_user)?.mes ||
[...chat].reverse().find((message) => message?.is_user)?.mes ||
""
);
}
function buildStructuredSnapshot(ctx = {}) {
const char = resolveCharacter(ctx);
const chat = Array.isArray(ctx.chat) ? safeClone(ctx.chat, []) : [];
const currentTime = new Date().toLocaleString("zh-CN");
const globalVars = safeClone(
ctx.extensionSettings?.variables?.global || {},
{},
);
const localVars = safeClone(ctx.chatMetadata?.variables || {}, {});
return {
persona: {
text: resolvePersona(ctx),
lorebook:
ctx.extensionSettings?.persona_description_lorebook ||
ctx.powerUserSettings?.persona_description_lorebook ||
ctx.power_user?.persona_description_lorebook ||
"",
},
character: {
id: ctx.characterId ?? null,
name: ctx.name2 || char?.name || "",
description: resolveCharacterDescription(char),
avatar: char?.avatar ? `/characters/${char.avatar}` : "",
worldbook: char?.data?.extensions?.world || char?.extensions?.world || "",
raw: safeClone(char, null),
},
user: {
name: ctx.name1 || "",
avatar: "",
raw: safeClone(ctx.user || null, null),
},
chat: {
id: ctx.chatId || globalThis.getCurrentChatId?.() || "",
messages: chat,
lastUserMessage: resolveLastUserMessage(chat),
},
worldbook: {
character: char?.data?.extensions?.world || char?.extensions?.world || "",
persona:
ctx.extensionSettings?.persona_description_lorebook ||
ctx.powerUserSettings?.persona_description_lorebook ||
ctx.power_user?.persona_description_lorebook ||
"",
chat: ctx.chatMetadata?.world || "",
},
variables: {
global: globalVars,
local: localVars,
merged: {
...globalVars,
...localVars,
},
},
time: {
current: currentTime,
locale: "zh-CN",
},
host: {
meta: {
onlineStatus: ctx.onlineStatus || "",
selectedGroupId: ctx.selectedGroupId ?? null,
},
capabilities: {
hasGetContext: typeof getContext === "function",
hasGlobalGetContext:
typeof globalThis.SillyTavern?.getContext === "function",
hasCurrentChatId: typeof globalThis.getCurrentChatId === "function",
},
},
raw: safeClone(ctx, {}),
};
}
function buildCompatPromptAliases(snapshot) {
return {
userPersona: snapshot.persona.text,
charDescription: snapshot.character.description,
charName: snapshot.character.name,
userName: snapshot.user.name,
currentTime: snapshot.time.current,
};
}
export function getSTContextSnapshot() {
try {
const ctx = getContext?.() || {};
const snapshot = buildStructuredSnapshot(ctx);
return {
snapshot,
prompt: buildCompatPromptAliases(snapshot),
};
} catch (e) {
console.warn("[ST-BME] getSTContextSnapshot 失败:", e);
const snapshot = buildStructuredSnapshot({});
return {
snapshot,
prompt: buildCompatPromptAliases(snapshot),
};
}
}
/**
* 从 SillyTavern 的 getContext() 提取当前上下文数据,
* 返回的字段可直接展开传入 buildTaskPrompt 的 context 参数,
@@ -11,37 +170,5 @@ import { getContext } from "../../../extensions.js";
* @returns {object} 上下文字段映射
*/
export function getSTContextForPrompt() {
try {
const ctx = getContext?.() || {};
const charId = ctx.characterId;
const char =
ctx.characters?.[Number(charId)] ||
ctx.characters?.[charId] ||
null;
return {
userPersona:
ctx.powerUserSettings?.persona_description ||
ctx.extensionSettings?.persona_description ||
ctx.name1_description ||
ctx.persona ||
"",
charDescription:
char?.description ||
char?.data?.description ||
"",
charName: ctx.name2 || "",
userName: ctx.name1 || "",
currentTime: new Date().toLocaleString("zh-CN"),
};
} catch (e) {
console.warn("[ST-BME] getSTContextForPrompt 失败:", e);
return {
userPersona: "",
charDescription: "",
charName: "",
userName: "",
currentTime: new Date().toLocaleString("zh-CN"),
};
}
return getSTContextSnapshot().prompt;
}