mirror of
https://github.com/Youzini-afk/ST-Bionic-Memory-Ecology.git
synced 2026-06-14 02:40:45 +08:00
feat: MVU规则模块+世界书MVU过滤+prompt组装MVU清洗+端到端测试
This commit is contained in:
56
tests/mvu-compat.mjs
Normal file
56
tests/mvu-compat.mjs
Normal file
@@ -0,0 +1,56 @@
|
||||
import assert from "node:assert/strict";
|
||||
|
||||
const {
|
||||
isLikelyMvuWorldInfoContent,
|
||||
isMvuTaggedWorldInfoNameOrComment,
|
||||
sanitizeMvuContent,
|
||||
} = await import("../mvu-compat.js");
|
||||
|
||||
assert.equal(
|
||||
isMvuTaggedWorldInfoNameOrComment("[mvu_update] 状态", ""),
|
||||
true,
|
||||
);
|
||||
assert.equal(
|
||||
isMvuTaggedWorldInfoNameOrComment("普通条目", "[initvar]"),
|
||||
true,
|
||||
);
|
||||
assert.equal(
|
||||
isLikelyMvuWorldInfoContent(
|
||||
"变量更新规则:\ntype: state\n当前时间: 12:00",
|
||||
),
|
||||
true,
|
||||
);
|
||||
assert.equal(isLikelyMvuWorldInfoContent("正常世界设定"), false);
|
||||
|
||||
const aggressive = sanitizeMvuContent(
|
||||
"正文\n<updatevariable>hp=1</updatevariable>\n<status_current_variable>secret</status_current_variable>",
|
||||
{
|
||||
mode: "aggressive",
|
||||
},
|
||||
);
|
||||
assert.equal(aggressive.text, "");
|
||||
assert.equal(aggressive.dropped, true);
|
||||
assert.deepEqual(
|
||||
aggressive.reasons.sort(),
|
||||
["artifact_stripped", "likely_mvu_content"].sort(),
|
||||
);
|
||||
|
||||
const finalSafe = sanitizeMvuContent(
|
||||
"说明文字\n<updatevariable>hp=1</updatevariable>\n尾巴",
|
||||
{
|
||||
mode: "final-safe",
|
||||
},
|
||||
);
|
||||
assert.equal(finalSafe.dropped, false);
|
||||
assert.equal(finalSafe.text, "说明文字\n尾巴");
|
||||
assert.deepEqual(finalSafe.reasons, ["artifact_stripped"]);
|
||||
|
||||
const blocked = sanitizeMvuContent("前缀\n被拦截条目\n后缀", {
|
||||
mode: "final-safe",
|
||||
blockedContents: ["被拦截条目"],
|
||||
});
|
||||
assert.equal(blocked.text, "前缀\n\n后缀");
|
||||
assert.equal(blocked.blockedHitCount, 1);
|
||||
assert.deepEqual(blocked.reasons, ["blocked_content_removed"]);
|
||||
|
||||
console.log("mvu-compat tests passed");
|
||||
@@ -2,6 +2,7 @@ import assert from "node:assert/strict";
|
||||
import fs from "node:fs/promises";
|
||||
import { createRequire, registerHooks } from "node:module";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import vm from "node:vm";
|
||||
|
||||
const extensionsShimSource = [
|
||||
@@ -34,6 +35,8 @@ const scriptShimUrl = `data:text/javascript,${encodeURIComponent(
|
||||
const openAiShimUrl = `data:text/javascript,${encodeURIComponent(
|
||||
openAiShimSource,
|
||||
)}`;
|
||||
const moduleDir = path.dirname(fileURLToPath(import.meta.url));
|
||||
const indexPath = path.resolve(moduleDir, "../index.js");
|
||||
|
||||
registerHooks({
|
||||
resolve(specifier, context, nextResolve) {
|
||||
@@ -138,7 +141,6 @@ const schema = [
|
||||
];
|
||||
|
||||
function createBatchStageHarness() {
|
||||
const indexPath = path.resolve("./index.js");
|
||||
return fs.readFile(indexPath, "utf8").then((source) => {
|
||||
const marker = "function isAssistantChatMessage(message) {";
|
||||
const start = source.indexOf("function shouldAdvanceProcessedHistory(");
|
||||
@@ -181,7 +183,6 @@ function createBatchStageHarness() {
|
||||
}
|
||||
|
||||
function createGenerationRecallHarness() {
|
||||
const indexPath = path.resolve("./index.js");
|
||||
return fs.readFile(indexPath, "utf8").then((source) => {
|
||||
const start = source.indexOf("const RECALL_INPUT_RECORD_TTL_MS = 60000;");
|
||||
const end = source.indexOf("function onMessageReceived() {");
|
||||
@@ -243,7 +244,6 @@ function createGenerationRecallHarness() {
|
||||
}
|
||||
|
||||
function createRerollHarness() {
|
||||
const indexPath = path.resolve("./index.js");
|
||||
return fs.readFile(indexPath, "utf8").then((source) => {
|
||||
const helperStart = source.indexOf(
|
||||
"function pruneProcessedMessageHashesFromFloor(",
|
||||
|
||||
@@ -2,6 +2,7 @@ import assert from "node:assert/strict";
|
||||
import { registerHooks } from "node:module";
|
||||
|
||||
const extensionsShimSource = [
|
||||
"export const extension_settings = {};",
|
||||
"export function getContext() {",
|
||||
" return {",
|
||||
" chat: [],",
|
||||
|
||||
333
tests/prompt-builder-mvu.mjs
Normal file
333
tests/prompt-builder-mvu.mjs
Normal file
@@ -0,0 +1,333 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { createRequire, registerHooks } from "node:module";
|
||||
|
||||
const extensionsShimSource = [
|
||||
"export const extension_settings = globalThis.__promptBuilderMvuExtensionSettings || {};",
|
||||
"export function getContext() {",
|
||||
" return globalThis.__promptBuilderMvuContext || {",
|
||||
" chat: [],",
|
||||
" chatMetadata: {},",
|
||||
" extensionSettings: {},",
|
||||
" powerUserSettings: {},",
|
||||
" characters: [],",
|
||||
" characterId: null,",
|
||||
" name1: '',",
|
||||
" name2: '',",
|
||||
" chatId: 'mvu-test-chat',",
|
||||
" };",
|
||||
"}",
|
||||
].join("\n");
|
||||
const scriptShimSource = [
|
||||
"export function getRequestHeaders() {",
|
||||
" return { 'Content-Type': 'application/json' };",
|
||||
"}",
|
||||
].join("\n");
|
||||
const openAiShimSource = [
|
||||
"export const chat_completion_sources = { CUSTOM: 'custom', OPENAI: 'openai' };",
|
||||
"export async function sendOpenAIRequest(...args) {",
|
||||
" if (typeof globalThis.__promptBuilderMvuSendOpenAIRequest === 'function') {",
|
||||
" return await globalThis.__promptBuilderMvuSendOpenAIRequest(...args);",
|
||||
" }",
|
||||
" return { choices: [{ message: { content: '{}' } }] };",
|
||||
"}",
|
||||
].join("\n");
|
||||
|
||||
registerHooks({
|
||||
resolve(specifier, context, nextResolve) {
|
||||
if (
|
||||
specifier === "../../../extensions.js" ||
|
||||
specifier === "../../../../extensions.js"
|
||||
) {
|
||||
return {
|
||||
shortCircuit: true,
|
||||
url: `data:text/javascript,${encodeURIComponent(extensionsShimSource)}`,
|
||||
};
|
||||
}
|
||||
if (specifier === "../../../../script.js") {
|
||||
return {
|
||||
shortCircuit: true,
|
||||
url: `data:text/javascript,${encodeURIComponent(scriptShimSource)}`,
|
||||
};
|
||||
}
|
||||
if (specifier === "../../../openai.js") {
|
||||
return {
|
||||
shortCircuit: true,
|
||||
url: `data:text/javascript,${encodeURIComponent(openAiShimSource)}`,
|
||||
};
|
||||
}
|
||||
return nextResolve(specifier, context);
|
||||
},
|
||||
});
|
||||
|
||||
const require = createRequire(import.meta.url);
|
||||
const originalRequire = globalThis.require;
|
||||
const originalExtensionSettings = globalThis.__promptBuilderMvuExtensionSettings;
|
||||
const originalContext = globalThis.__promptBuilderMvuContext;
|
||||
const originalSendOpenAIRequest = globalThis.__promptBuilderMvuSendOpenAIRequest;
|
||||
const originalFetch = globalThis.fetch;
|
||||
|
||||
globalThis.require = require;
|
||||
globalThis.__promptBuilderMvuExtensionSettings = {
|
||||
st_bme: {},
|
||||
};
|
||||
globalThis.__promptBuilderMvuContext = {
|
||||
chat: [],
|
||||
chatMetadata: {},
|
||||
extensionSettings: {},
|
||||
powerUserSettings: {},
|
||||
characters: [],
|
||||
characterId: null,
|
||||
name1: "User",
|
||||
name2: "Alice",
|
||||
chatId: "mvu-test-chat",
|
||||
};
|
||||
|
||||
try {
|
||||
const extensionsApi = await import("../../../../extensions.js");
|
||||
const { createDefaultTaskProfiles } = await import("../prompt-profiles.js");
|
||||
const {
|
||||
buildTaskExecutionDebugContext,
|
||||
buildTaskLlmPayload,
|
||||
buildTaskPrompt,
|
||||
} = await import("../prompt-builder.js");
|
||||
const llm = await import("../llm.js");
|
||||
|
||||
function createRule(id, findRegex, replaceString) {
|
||||
return {
|
||||
id,
|
||||
script_name: id,
|
||||
enabled: true,
|
||||
find_regex: findRegex,
|
||||
replace_string: replaceString,
|
||||
source: {
|
||||
user_input: true,
|
||||
ai_output: true,
|
||||
},
|
||||
destination: {
|
||||
prompt: true,
|
||||
display: false,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function buildSettings() {
|
||||
const taskProfiles = createDefaultTaskProfiles();
|
||||
const recallProfile = taskProfiles.recall.profiles[0];
|
||||
recallProfile.generation = {
|
||||
...recallProfile.generation,
|
||||
stream: false,
|
||||
};
|
||||
recallProfile.regex = {
|
||||
enabled: true,
|
||||
inheritStRegex: false,
|
||||
sources: {
|
||||
global: false,
|
||||
preset: false,
|
||||
character: false,
|
||||
},
|
||||
stages: {
|
||||
"input.userMessage": true,
|
||||
"input.recentMessages": true,
|
||||
"input.candidateText": true,
|
||||
"input.finalPrompt": true,
|
||||
},
|
||||
localRules: [
|
||||
createRule("user-rule", "/BAD_USER/g", "GOOD_USER"),
|
||||
createRule("recent-rule", "/BAD_RECENT/g", "GOOD_RECENT"),
|
||||
createRule("candidate-rule", "/BAD_CANDIDATE/g", "GOOD_CANDIDATE"),
|
||||
createRule("final-rule", "/FINAL_BAD/g", "FINAL_GOOD"),
|
||||
],
|
||||
};
|
||||
recallProfile.blocks.push({
|
||||
id: "mvu-final-custom",
|
||||
name: "最终检查块",
|
||||
type: "custom",
|
||||
enabled: true,
|
||||
role: "system",
|
||||
sourceKey: "",
|
||||
sourceField: "",
|
||||
content: "FINAL_BAD",
|
||||
injectionMode: "append",
|
||||
order: recallProfile.blocks.length,
|
||||
});
|
||||
|
||||
return {
|
||||
llmApiUrl: "https://example.com/v1",
|
||||
llmApiKey: "sk-mvu-secret",
|
||||
llmModel: "gpt-mvu-test",
|
||||
timeoutMs: 4321,
|
||||
taskProfilesVersion: 3,
|
||||
taskProfiles,
|
||||
};
|
||||
}
|
||||
|
||||
const settings = buildSettings();
|
||||
extensionsApi.extension_settings.st_bme = settings;
|
||||
delete globalThis.__stBmeRuntimeDebugState;
|
||||
|
||||
const promptBuild = await buildTaskPrompt(settings, "recall", {
|
||||
taskName: "recall",
|
||||
charDescription: "角色设定 <StatusPlaceHolderImpl/> BAD_RECENT",
|
||||
userPersona: "变量更新规则:\ntype: state\n当前时间: 12:00",
|
||||
recentMessages:
|
||||
"最近消息 <status_current_variable>hp=3</status_current_variable> BAD_RECENT",
|
||||
userMessage:
|
||||
"用户输入 <updatevariable>secret</updatevariable> BAD_USER",
|
||||
candidateNodes: "候选节点 BAD_CANDIDATE",
|
||||
candidateText: "候选节点 BAD_CANDIDATE",
|
||||
graphStats: "candidate_count=1",
|
||||
});
|
||||
|
||||
assert.match(promptBuild.systemPrompt, /GOOD_RECENT/);
|
||||
assert.match(JSON.stringify(promptBuild.executionMessages), /GOOD_USER/);
|
||||
assert.match(JSON.stringify(promptBuild.executionMessages), /GOOD_CANDIDATE/);
|
||||
assert.match(promptBuild.systemPrompt, /FINAL_GOOD/);
|
||||
assert.doesNotMatch(
|
||||
JSON.stringify(promptBuild),
|
||||
/status_current_variable|updatevariable|StatusPlaceHolderImpl/i,
|
||||
);
|
||||
assert.equal(promptBuild.debug.mvu.sanitizedFieldCount >= 4, true);
|
||||
assert.equal(promptBuild.debug.mvu.finalMessageStripCount >= 1, true);
|
||||
assert.equal(Array.isArray(promptBuild.regexInput?.entries), true);
|
||||
assert.equal(promptBuild.regexInput.entries.length > 0, true);
|
||||
|
||||
const systemOnlySettings = buildSettings();
|
||||
systemOnlySettings.taskProfiles.recall = {
|
||||
activeProfileId: "system-only",
|
||||
profiles: [
|
||||
{
|
||||
id: "system-only",
|
||||
name: "system only",
|
||||
taskType: "recall",
|
||||
builtin: false,
|
||||
blocks: [
|
||||
{
|
||||
id: "only-system",
|
||||
name: "Only System",
|
||||
type: "custom",
|
||||
enabled: true,
|
||||
role: "system",
|
||||
sourceKey: "",
|
||||
sourceField: "",
|
||||
content: "系统块",
|
||||
injectionMode: "append",
|
||||
order: 0,
|
||||
},
|
||||
],
|
||||
generation: createDefaultTaskProfiles().recall.profiles[0].generation,
|
||||
regex: {
|
||||
enabled: false,
|
||||
inheritStRegex: false,
|
||||
stages: {},
|
||||
localRules: [],
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const systemOnlyPromptBuild = await buildTaskPrompt(systemOnlySettings, "recall", {
|
||||
taskName: "recall",
|
||||
});
|
||||
const systemOnlyPayload = buildTaskLlmPayload(
|
||||
systemOnlyPromptBuild,
|
||||
"fallback <updatevariable>hidden</updatevariable> text",
|
||||
);
|
||||
assert.equal(systemOnlyPayload.userPrompt, "fallback text");
|
||||
|
||||
const capturedBodies = [];
|
||||
globalThis.fetch = async (_url, options = {}) => {
|
||||
capturedBodies.push(JSON.parse(String(options.body || "{}")));
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
choices: [
|
||||
{
|
||||
message: {
|
||||
content: '{"ok":true}',
|
||||
},
|
||||
finish_reason: "stop",
|
||||
},
|
||||
],
|
||||
}),
|
||||
{
|
||||
status: 200,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
const payload = buildTaskLlmPayload(promptBuild, "unused fallback");
|
||||
const result = await llm.callLLMForJSON({
|
||||
systemPrompt: payload.systemPrompt,
|
||||
userPrompt: payload.userPrompt,
|
||||
maxRetries: 0,
|
||||
taskType: "recall",
|
||||
promptMessages: payload.promptMessages,
|
||||
additionalMessages: payload.additionalMessages,
|
||||
debugContext: buildTaskExecutionDebugContext(promptBuild),
|
||||
});
|
||||
|
||||
assert.deepEqual(result, { ok: true });
|
||||
assert.equal(capturedBodies.length, 1);
|
||||
assert.doesNotMatch(
|
||||
JSON.stringify(capturedBodies[0].messages),
|
||||
/status_current_variable|updatevariable|StatusPlaceHolderImpl/i,
|
||||
);
|
||||
|
||||
const runtimePromptBuild =
|
||||
globalThis.__stBmeRuntimeDebugState?.taskPromptBuilds?.recall || null;
|
||||
const runtimeLlmRequest =
|
||||
globalThis.__stBmeRuntimeDebugState?.taskLlmRequests?.recall || null;
|
||||
|
||||
assert.ok(runtimePromptBuild);
|
||||
assert.ok(runtimeLlmRequest);
|
||||
assert.doesNotMatch(
|
||||
JSON.stringify(runtimePromptBuild.executionMessages),
|
||||
/status_current_variable|updatevariable|StatusPlaceHolderImpl/i,
|
||||
);
|
||||
assert.doesNotMatch(
|
||||
JSON.stringify(runtimeLlmRequest.messages),
|
||||
/status_current_variable|updatevariable|StatusPlaceHolderImpl/i,
|
||||
);
|
||||
assert.doesNotMatch(
|
||||
JSON.stringify(runtimeLlmRequest.requestBody?.messages || []),
|
||||
/status_current_variable|updatevariable|StatusPlaceHolderImpl/i,
|
||||
);
|
||||
assert.deepEqual(
|
||||
runtimeLlmRequest.messages,
|
||||
runtimeLlmRequest.requestBody.messages,
|
||||
);
|
||||
assert.equal(
|
||||
runtimeLlmRequest.promptExecution?.mvu?.sanitizedFieldCount,
|
||||
promptBuild.debug.mvu.sanitizedFieldCount,
|
||||
);
|
||||
|
||||
console.log("prompt-builder-mvu tests passed");
|
||||
} finally {
|
||||
if (originalRequire === undefined) {
|
||||
delete globalThis.require;
|
||||
} else {
|
||||
globalThis.require = originalRequire;
|
||||
}
|
||||
|
||||
if (originalExtensionSettings === undefined) {
|
||||
delete globalThis.__promptBuilderMvuExtensionSettings;
|
||||
} else {
|
||||
globalThis.__promptBuilderMvuExtensionSettings = originalExtensionSettings;
|
||||
}
|
||||
|
||||
if (originalContext === undefined) {
|
||||
delete globalThis.__promptBuilderMvuContext;
|
||||
} else {
|
||||
globalThis.__promptBuilderMvuContext = originalContext;
|
||||
}
|
||||
|
||||
if (originalSendOpenAIRequest === undefined) {
|
||||
delete globalThis.__promptBuilderMvuSendOpenAIRequest;
|
||||
} else {
|
||||
globalThis.__promptBuilderMvuSendOpenAIRequest = originalSendOpenAIRequest;
|
||||
}
|
||||
|
||||
globalThis.fetch = originalFetch;
|
||||
}
|
||||
@@ -2,6 +2,7 @@ import assert from "node:assert/strict";
|
||||
import { registerHooks } from "node:module";
|
||||
|
||||
const extensionsShimSource = [
|
||||
"export const extension_settings = {};",
|
||||
"export function getContext(...args) {",
|
||||
" return globalThis.SillyTavern?.getContext?.(...args) || null;",
|
||||
"}",
|
||||
@@ -147,6 +148,30 @@ const atDepthEntry = createWorldbookEntry({
|
||||
order: 5,
|
||||
});
|
||||
|
||||
const mvuTaggedEntry = createWorldbookEntry({
|
||||
uid: 9,
|
||||
name: "[mvu_update] 状态同步",
|
||||
comment: "MVU tagged",
|
||||
content: "这一条不应该进入结果。",
|
||||
order: 28,
|
||||
});
|
||||
|
||||
const mvuHeuristicEntry = createWorldbookEntry({
|
||||
uid: 10,
|
||||
name: "MVU 启发式条目",
|
||||
comment: "MVU heuristic",
|
||||
content: "<status_current_variable>secret=true</status_current_variable>",
|
||||
order: 29,
|
||||
});
|
||||
|
||||
const mvuLazyProbeEntry = createWorldbookEntry({
|
||||
uid: 11,
|
||||
name: "MVU 懒加载探测",
|
||||
comment: "MVU 懒加载探测",
|
||||
content: 'MVU lazy: <%= await getwi("bonus-book", "Bonus MVU") %>',
|
||||
order: 27,
|
||||
});
|
||||
|
||||
const bonusEntry = createWorldbookEntry({
|
||||
uid: 101,
|
||||
name: "Bonus 条目",
|
||||
@@ -155,6 +180,14 @@ const bonusEntry = createWorldbookEntry({
|
||||
order: 10,
|
||||
});
|
||||
|
||||
const bonusMvuEntry = createWorldbookEntry({
|
||||
uid: 102,
|
||||
name: "Bonus MVU",
|
||||
comment: "Bonus MVU",
|
||||
content: "变量更新规则:\ntype: sync\n当前时间: 12:00",
|
||||
order: 20,
|
||||
});
|
||||
|
||||
const worldbooksByName = {
|
||||
"main-book": [
|
||||
constantEntry,
|
||||
@@ -162,11 +195,14 @@ const worldbooksByName = {
|
||||
inlineSummaryEntry,
|
||||
extensionLiteralEntry,
|
||||
externalInlineEntry,
|
||||
mvuLazyProbeEntry,
|
||||
forceControlEntry,
|
||||
forcedAfterEntry,
|
||||
atDepthEntry,
|
||||
mvuTaggedEntry,
|
||||
mvuHeuristicEntry,
|
||||
],
|
||||
"bonus-book": [bonusEntry],
|
||||
"bonus-book": [bonusEntry, bonusMvuEntry],
|
||||
};
|
||||
|
||||
try {
|
||||
@@ -217,16 +253,18 @@ try {
|
||||
|
||||
assert.deepEqual(
|
||||
worldInfo.beforeEntries.map((entry) => entry.name),
|
||||
["常驻设定", "EJS 汇总", "扩展语义正文", "外部书汇总"],
|
||||
["常驻设定", "EJS 汇总", "扩展语义正文", "外部书汇总", "MVU 懒加载探测"],
|
||||
);
|
||||
assert.deepEqual(worldInfo.afterEntries.map((entry) => entry.name), ["强制后置"]);
|
||||
assert.equal(worldInfo.additionalMessages.length, 1);
|
||||
assert.equal(worldInfo.additionalMessages[0].content, "这是一条 atDepth 消息。");
|
||||
assert.match(worldInfo.beforeText, /控制摘要:隐藏线索:Alice 正在调查。/);
|
||||
assert.match(worldInfo.beforeText, /外部补充:来自 bonus-book 的补充内容。/);
|
||||
assert.match(worldInfo.beforeText, /MVU lazy:/);
|
||||
assert.match(worldInfo.beforeText, /@@generate/);
|
||||
assert.match(worldInfo.beforeText, /\[GENERATE:Test\]/);
|
||||
assert.doesNotMatch(worldInfo.beforeText, /getwi|<%=?/);
|
||||
assert.doesNotMatch(worldInfo.beforeText, /status_current_variable|变量更新规则|updatevariable/i);
|
||||
assert.equal(worldInfo.debug.ejsInlinePullCount, 2);
|
||||
assert.equal(worldInfo.debug.ejsForcedActivationCount, 1);
|
||||
assert.equal(worldInfo.debug.resolvePassCount >= 2, true);
|
||||
@@ -238,10 +276,23 @@ try {
|
||||
["Bonus 条目", "线索条目"].sort(),
|
||||
);
|
||||
assert.deepEqual(worldInfo.debug.lazyLoadedWorldbooks, ["bonus-book"]);
|
||||
assert.equal(worldInfo.debug.mvu.filteredEntryCount, 2);
|
||||
assert.equal(worldInfo.debug.mvu.lazyFilteredEntryCount, 1);
|
||||
assert.equal(worldInfo.debug.mvu.blockedContentsCount, 3);
|
||||
assert.deepEqual(
|
||||
worldInfo.debug.mvu.filteredEntries.map((entry) => entry.sourceName).sort(),
|
||||
["[mvu_update] 状态同步", "MVU 启发式条目", "Bonus MVU"].sort(),
|
||||
);
|
||||
assert.equal(
|
||||
worldInfo.debug.warnings.some((warning) => warning.includes("旧 EW 命名条目")),
|
||||
true,
|
||||
);
|
||||
assert.equal(
|
||||
worldInfo.debug.recursionWarnings.some((warning) =>
|
||||
warning.includes("mvu filtered world info blocked"),
|
||||
),
|
||||
true,
|
||||
);
|
||||
|
||||
const settings = {
|
||||
taskProfiles: {
|
||||
@@ -299,7 +350,9 @@ try {
|
||||
assert.match(promptBuild.systemPrompt, /控制摘要:隐藏线索:Alice 正在调查/);
|
||||
assert.match(promptBuild.systemPrompt, /扩展语义只是普通文本/);
|
||||
assert.match(promptBuild.systemPrompt, /来自 bonus-book 的补充内容/);
|
||||
assert.match(promptBuild.systemPrompt, /MVU lazy:/);
|
||||
assert.doesNotMatch(promptBuild.systemPrompt, /getwi|<%=?/);
|
||||
assert.doesNotMatch(promptBuild.systemPrompt, /status_current_variable|变量更新规则|updatevariable/i);
|
||||
assert.equal(
|
||||
promptBuild.privateTaskMessages.length,
|
||||
2,
|
||||
@@ -311,7 +364,7 @@ try {
|
||||
);
|
||||
assert.deepEqual(
|
||||
promptBuild.hostInjections.before.map((entry) => entry.name),
|
||||
["常驻设定", "EJS 汇总", "扩展语义正文", "外部书汇总"],
|
||||
["常驻设定", "EJS 汇总", "扩展语义正文", "外部书汇总", "MVU 懒加载探测"],
|
||||
);
|
||||
assert.deepEqual(
|
||||
promptBuild.hostInjections.after.map((entry) => entry.name),
|
||||
@@ -327,6 +380,7 @@ try {
|
||||
"EJS 汇总",
|
||||
"扩展语义正文",
|
||||
"外部书汇总",
|
||||
"MVU 懒加载探测",
|
||||
]);
|
||||
assert.equal(promptBuild.hostInjectionPlan.after.length, 1);
|
||||
assert.equal(promptBuild.hostInjectionPlan.after[0].blockId, "b2");
|
||||
@@ -346,6 +400,7 @@ try {
|
||||
);
|
||||
assert.equal(promptBuild.additionalMessages.length, 1);
|
||||
assert.equal(promptBuild.additionalMessages[0].content, "这是一条 atDepth 消息。");
|
||||
assert.equal(promptBuild.debug.mvu.sanitizedFieldCount >= 0, true);
|
||||
|
||||
const { initializeHostAdapter } = await import("../host-adapter/index.js");
|
||||
const partialBridgeCalls = [];
|
||||
|
||||
Reference in New Issue
Block a user