mirror of
https://github.com/Youzini-afk/ST-Bionic-Memory-Ecology.git
synced 2026-05-15 22:30:38 +08:00
863 lines
23 KiB
JavaScript
863 lines
23 KiB
JavaScript
import assert from "node:assert/strict";
|
||
import {
|
||
LEGACY_PLANNER_SYSTEM_PROMPT,
|
||
PLANNER_ASSISTANT_SEED,
|
||
} from "../ena-planner/ena-planner-presets.js";
|
||
import {
|
||
createDefaultTaskProfiles,
|
||
ensureTaskProfiles,
|
||
getActiveTaskProfile,
|
||
migrateLegacyProfileRegexToGlobal,
|
||
migrateLegacyTaskProfiles,
|
||
migratePerTaskRegexToGlobal,
|
||
normalizeTaskProfile,
|
||
} from "../prompting/prompt-profiles.js";
|
||
|
||
const legacySettings = {
|
||
extractPrompt: "旧提取提示",
|
||
recallPrompt: "旧召回提示",
|
||
compressPrompt: "",
|
||
synopsisPrompt: "",
|
||
reflectionPrompt: "",
|
||
consolidationPrompt: "",
|
||
};
|
||
|
||
const migrated = migrateLegacyTaskProfiles(legacySettings);
|
||
assert.equal(migrated.taskProfilesVersion, 3);
|
||
assert.ok(migrated.taskProfiles);
|
||
assert.ok(migrated.taskProfiles.extract);
|
||
assert.ok(migrated.taskProfiles.recall);
|
||
assert.ok(migrated.taskProfiles.planner);
|
||
|
||
const extractProfile = getActiveTaskProfile(
|
||
{
|
||
...legacySettings,
|
||
taskProfiles: migrated.taskProfiles,
|
||
},
|
||
"extract",
|
||
);
|
||
assert.equal(extractProfile.taskType, "extract");
|
||
assert.equal(extractProfile.id, "default");
|
||
assert.ok(Array.isArray(extractProfile.blocks));
|
||
assert.equal(extractProfile.blocks.length, 16);
|
||
assert.deepEqual(
|
||
extractProfile.blocks.map((block) => block.name),
|
||
[
|
||
"抬头",
|
||
"角色定义",
|
||
"身份确认",
|
||
"角色描述",
|
||
"用户设定",
|
||
"世界书前块",
|
||
"世界书后块",
|
||
"图统计",
|
||
"Schema",
|
||
"活跃总结",
|
||
"故事时间",
|
||
"当前范围",
|
||
"最近消息",
|
||
"信息确认",
|
||
"输出格式",
|
||
"行为规则",
|
||
],
|
||
);
|
||
assert.deepEqual(
|
||
extractProfile.blocks.map((block) => block.type),
|
||
[
|
||
"custom",
|
||
"custom",
|
||
"custom",
|
||
"builtin",
|
||
"builtin",
|
||
"builtin",
|
||
"builtin",
|
||
"builtin",
|
||
"builtin",
|
||
"builtin",
|
||
"builtin",
|
||
"builtin",
|
||
"builtin",
|
||
"custom",
|
||
"custom",
|
||
"custom",
|
||
],
|
||
);
|
||
assert.deepEqual(
|
||
extractProfile.blocks.map((block) => block.role),
|
||
[
|
||
"system",
|
||
"system",
|
||
"assistant",
|
||
"system",
|
||
"system",
|
||
"system",
|
||
"system",
|
||
"system",
|
||
"system",
|
||
"system",
|
||
"system",
|
||
"system",
|
||
"system",
|
||
"assistant",
|
||
"user",
|
||
"user",
|
||
],
|
||
);
|
||
assert.equal(
|
||
extractProfile.metadata.legacyPromptField,
|
||
"extractPrompt",
|
||
);
|
||
assert.equal(
|
||
extractProfile.metadata.legacyPromptSnapshot,
|
||
"旧提取提示",
|
||
);
|
||
|
||
const defaults = createDefaultTaskProfiles();
|
||
assert.ok(defaults.extract.profiles.length > 0);
|
||
assert.ok(defaults.recall.profiles.length > 0);
|
||
assert.ok(defaults.compress.profiles.length > 0);
|
||
assert.ok(defaults.synopsis.profiles.length > 0);
|
||
assert.ok(defaults.reflection.profiles.length > 0);
|
||
assert.deepEqual(
|
||
defaults.recall.profiles[0].blocks.map((block) => block.sourceKey || block.id),
|
||
[
|
||
"default-heading",
|
||
"default-role",
|
||
"default-identity-ack",
|
||
"charDescription",
|
||
"userPersona",
|
||
"worldInfoBefore",
|
||
"worldInfoAfter",
|
||
"graphStats",
|
||
"sceneOwnerCandidates",
|
||
"candidateNodes",
|
||
"recentMessages",
|
||
"userMessage",
|
||
"default-info-ack",
|
||
"default-format",
|
||
"default-rules",
|
||
],
|
||
);
|
||
assert.deepEqual(
|
||
defaults.synopsis.profiles[0].blocks.map((block) => block.sourceKey || block.id),
|
||
[
|
||
"default-heading",
|
||
"default-role",
|
||
"default-identity-ack",
|
||
"charDescription",
|
||
"userPersona",
|
||
"worldInfoBefore",
|
||
"worldInfoAfter",
|
||
"graphStats",
|
||
"candidateText",
|
||
"currentRange",
|
||
"recentMessages",
|
||
"default-info-ack",
|
||
"default-format",
|
||
"default-rules",
|
||
],
|
||
);
|
||
assert.ok(defaults.summary_rollup.profiles.length > 0);
|
||
assert.ok(defaults.planner.profiles.length > 0);
|
||
assert.deepEqual(
|
||
defaults.planner.profiles[0].blocks.map((block) => block.sourceKey || block.id),
|
||
[
|
||
"planner-default-heading",
|
||
"planner-default-role",
|
||
"planner-default-identity-ack",
|
||
"plannerCharacterCard",
|
||
"plannerWorldbook",
|
||
"plannerMemory",
|
||
"plannerPreviousPlots",
|
||
"plannerRecentChat",
|
||
"plannerUserInput",
|
||
"planner-default-info-ack",
|
||
"planner-default-format",
|
||
"planner-default-rules",
|
||
"planner-default-assistant-seed",
|
||
],
|
||
);
|
||
assert.equal(defaults.planner.profiles[0].generation.stream, true);
|
||
assert.equal(defaults.planner.profiles[0].generation.temperature, 1);
|
||
|
||
const currentDefaultPlanner = defaults.planner.profiles[0];
|
||
const cloneValue = (value) => JSON.parse(JSON.stringify(value));
|
||
|
||
function buildLegacyPlannerDefaultLikeBlocks() {
|
||
return [
|
||
{
|
||
id: "planner-legacy-default-system",
|
||
name: "Ena Planner System",
|
||
type: "custom",
|
||
enabled: true,
|
||
role: "system",
|
||
sourceKey: "",
|
||
sourceField: "",
|
||
content: LEGACY_PLANNER_SYSTEM_PROMPT,
|
||
injectionMode: "relative",
|
||
order: 0,
|
||
},
|
||
{
|
||
id: "planner-legacy-default-char",
|
||
name: "角色卡",
|
||
type: "builtin",
|
||
enabled: true,
|
||
role: "system",
|
||
sourceKey: "plannerCharacterCard",
|
||
sourceField: "",
|
||
content: "",
|
||
injectionMode: "relative",
|
||
order: 1,
|
||
},
|
||
{
|
||
id: "planner-legacy-default-worldbook",
|
||
name: "世界书",
|
||
type: "builtin",
|
||
enabled: true,
|
||
role: "system",
|
||
sourceKey: "plannerWorldbook",
|
||
sourceField: "",
|
||
content: "",
|
||
injectionMode: "relative",
|
||
order: 2,
|
||
},
|
||
{
|
||
id: "planner-legacy-default-recent-chat",
|
||
name: "最近聊天",
|
||
type: "builtin",
|
||
enabled: true,
|
||
role: "system",
|
||
sourceKey: "plannerRecentChat",
|
||
sourceField: "",
|
||
content: "",
|
||
injectionMode: "relative",
|
||
order: 3,
|
||
},
|
||
{
|
||
id: "planner-legacy-default-memory",
|
||
name: "BME 记忆",
|
||
type: "builtin",
|
||
enabled: true,
|
||
role: "system",
|
||
sourceKey: "plannerMemory",
|
||
sourceField: "",
|
||
content: "",
|
||
injectionMode: "relative",
|
||
order: 4,
|
||
},
|
||
{
|
||
id: "planner-legacy-default-previous-plots",
|
||
name: "历史 plot",
|
||
type: "builtin",
|
||
enabled: true,
|
||
role: "system",
|
||
sourceKey: "plannerPreviousPlots",
|
||
sourceField: "",
|
||
content: "",
|
||
injectionMode: "relative",
|
||
order: 5,
|
||
},
|
||
{
|
||
id: "planner-legacy-default-user-input",
|
||
name: "玩家输入",
|
||
type: "builtin",
|
||
enabled: true,
|
||
role: "user",
|
||
sourceKey: "plannerUserInput",
|
||
sourceField: "",
|
||
content: "",
|
||
injectionMode: "relative",
|
||
order: 6,
|
||
},
|
||
{
|
||
id: "planner-legacy-default-seed",
|
||
name: "Assistant Seed",
|
||
type: "custom",
|
||
enabled: true,
|
||
role: "assistant",
|
||
sourceKey: "",
|
||
sourceField: "",
|
||
content: PLANNER_ASSISTANT_SEED,
|
||
injectionMode: "relative",
|
||
order: 7,
|
||
},
|
||
];
|
||
}
|
||
|
||
function createLegacyPlannerDefaultLikeProfile(overrides = {}) {
|
||
return {
|
||
id: "planner-legacy-default-like",
|
||
taskType: "planner",
|
||
builtin: false,
|
||
name: "ENA 当前配置",
|
||
promptMode: "block-based",
|
||
enabled: true,
|
||
updatedAt: "2026-04-23T00:00:00.000Z",
|
||
blocks: buildLegacyPlannerDefaultLikeBlocks(),
|
||
generation: cloneValue(currentDefaultPlanner.generation),
|
||
metadata: {
|
||
migratedFromLegacy: true,
|
||
enaLegacySource: "legacy-working-copy",
|
||
},
|
||
...overrides,
|
||
blocks: Array.isArray(overrides.blocks)
|
||
? overrides.blocks
|
||
: buildLegacyPlannerDefaultLikeBlocks(),
|
||
generation: {
|
||
...cloneValue(currentDefaultPlanner.generation),
|
||
...(overrides.generation || {}),
|
||
},
|
||
metadata: {
|
||
migratedFromLegacy: true,
|
||
enaLegacySource: "legacy-working-copy",
|
||
...(overrides.metadata || {}),
|
||
},
|
||
};
|
||
}
|
||
|
||
const legacyPlannerDefaultLikeProfile = createLegacyPlannerDefaultLikeProfile();
|
||
const alignedLegacyPlannerDefaults = ensureTaskProfiles({
|
||
taskProfilesVersion: 3,
|
||
taskProfiles: {
|
||
planner: {
|
||
activeProfileId: legacyPlannerDefaultLikeProfile.id,
|
||
profiles: [cloneValue(currentDefaultPlanner), legacyPlannerDefaultLikeProfile],
|
||
},
|
||
},
|
||
});
|
||
const alignedLegacyPlannerProfile = alignedLegacyPlannerDefaults.planner.profiles.find(
|
||
(profile) => profile.id === legacyPlannerDefaultLikeProfile.id,
|
||
);
|
||
assert.equal(alignedLegacyPlannerDefaults.planner.activeProfileId, "default");
|
||
assert.deepEqual(
|
||
alignedLegacyPlannerProfile.blocks.map((block) => block.sourceKey || block.id),
|
||
currentDefaultPlanner.blocks.map((block) => block.sourceKey || block.id),
|
||
);
|
||
assert.equal(alignedLegacyPlannerProfile.metadata.plannerLegacyDefaultAligned, true);
|
||
|
||
const legacyPlannerCustomGenerationProfile = createLegacyPlannerDefaultLikeProfile({
|
||
id: "planner-legacy-custom-generation",
|
||
generation: {
|
||
temperature: 0.7,
|
||
},
|
||
});
|
||
const alignedLegacyPlannerCustomGeneration = ensureTaskProfiles({
|
||
taskProfilesVersion: 3,
|
||
taskProfiles: {
|
||
planner: {
|
||
activeProfileId: legacyPlannerCustomGenerationProfile.id,
|
||
profiles: [
|
||
cloneValue(currentDefaultPlanner),
|
||
legacyPlannerCustomGenerationProfile,
|
||
],
|
||
},
|
||
},
|
||
});
|
||
const alignedLegacyPlannerCustomGenerationProfile =
|
||
alignedLegacyPlannerCustomGeneration.planner.profiles.find(
|
||
(profile) => profile.id === legacyPlannerCustomGenerationProfile.id,
|
||
);
|
||
assert.equal(
|
||
alignedLegacyPlannerCustomGeneration.planner.activeProfileId,
|
||
legacyPlannerCustomGenerationProfile.id,
|
||
);
|
||
assert.deepEqual(
|
||
alignedLegacyPlannerCustomGenerationProfile.blocks.map(
|
||
(block) => block.sourceKey || block.id,
|
||
),
|
||
currentDefaultPlanner.blocks.map((block) => block.sourceKey || block.id),
|
||
);
|
||
assert.equal(alignedLegacyPlannerCustomGenerationProfile.generation.temperature, 0.7);
|
||
|
||
const customizedLegacyPlannerBlocks = buildLegacyPlannerDefaultLikeBlocks();
|
||
customizedLegacyPlannerBlocks[0].content = `${customizedLegacyPlannerBlocks[0].content}\n\n自定义补充`;
|
||
const customizedLegacyPlannerProfile = createLegacyPlannerDefaultLikeProfile({
|
||
id: "planner-legacy-customized",
|
||
blocks: customizedLegacyPlannerBlocks,
|
||
});
|
||
const preservedCustomizedLegacyPlanner = ensureTaskProfiles({
|
||
taskProfilesVersion: 3,
|
||
taskProfiles: {
|
||
planner: {
|
||
activeProfileId: customizedLegacyPlannerProfile.id,
|
||
profiles: [cloneValue(currentDefaultPlanner), customizedLegacyPlannerProfile],
|
||
},
|
||
},
|
||
});
|
||
const preservedCustomizedLegacyPlannerProfile =
|
||
preservedCustomizedLegacyPlanner.planner.profiles.find(
|
||
(profile) => profile.id === customizedLegacyPlannerProfile.id,
|
||
);
|
||
assert.equal(
|
||
preservedCustomizedLegacyPlanner.planner.activeProfileId,
|
||
customizedLegacyPlannerProfile.id,
|
||
);
|
||
assert.match(
|
||
preservedCustomizedLegacyPlannerProfile.blocks[0].content,
|
||
/自定义补充/,
|
||
);
|
||
|
||
const upgradedLegacyDefault = getActiveTaskProfile(
|
||
{
|
||
taskProfilesVersion: 1,
|
||
taskProfiles: {
|
||
extract: {
|
||
activeProfileId: "default",
|
||
profiles: [
|
||
{
|
||
id: "default",
|
||
taskType: "extract",
|
||
builtin: true,
|
||
blocks: [
|
||
{
|
||
id: "default-role",
|
||
name: "角色定义",
|
||
type: "custom",
|
||
role: "system",
|
||
content: "保留我自己的角色定义",
|
||
order: 0,
|
||
},
|
||
{
|
||
id: "default-char-desc",
|
||
name: "角色描述",
|
||
type: "builtin",
|
||
role: "system",
|
||
sourceKey: "charDescription",
|
||
order: 1,
|
||
},
|
||
{
|
||
id: "default-user-persona",
|
||
name: "用户设定",
|
||
type: "builtin",
|
||
role: "system",
|
||
sourceKey: "userPersona",
|
||
order: 2,
|
||
},
|
||
{
|
||
id: "default-wi-before",
|
||
name: "世界书前块",
|
||
type: "builtin",
|
||
role: "system",
|
||
sourceKey: "worldInfoBefore",
|
||
order: 3,
|
||
},
|
||
{
|
||
id: "default-wi-after",
|
||
name: "世界书后块",
|
||
type: "builtin",
|
||
role: "system",
|
||
sourceKey: "worldInfoAfter",
|
||
order: 4,
|
||
},
|
||
{
|
||
id: "default-format",
|
||
name: "输出格式",
|
||
type: "custom",
|
||
role: "system",
|
||
content: "保留我自己的输出格式",
|
||
order: 5,
|
||
},
|
||
{
|
||
id: "default-rules",
|
||
name: "行为规则",
|
||
type: "custom",
|
||
role: "system",
|
||
content: "保留我自己的行为规则",
|
||
order: 6,
|
||
},
|
||
],
|
||
},
|
||
],
|
||
},
|
||
},
|
||
},
|
||
"extract",
|
||
);
|
||
assert.equal(upgradedLegacyDefault.blocks.length, 16);
|
||
assert.equal(upgradedLegacyDefault.blocks[0].name, "抬头");
|
||
assert.match(upgradedLegacyDefault.blocks[0].content, /虚拟的世界/);
|
||
assert.equal(upgradedLegacyDefault.blocks[0].role, "system");
|
||
assert.equal(upgradedLegacyDefault.blocks[0].injectionMode, "relative");
|
||
assert.equal(upgradedLegacyDefault.blocks[1].content, "保留我自己的角色定义");
|
||
const upgradedIdentityAck = upgradedLegacyDefault.blocks.find(
|
||
(block) => block.id === "default-identity-ack",
|
||
);
|
||
assert.ok(
|
||
upgradedIdentityAck,
|
||
"legacy upgrade should backfill default-identity-ack block",
|
||
);
|
||
assert.equal(upgradedIdentityAck.role, "assistant");
|
||
const upgradedInfoAck = upgradedLegacyDefault.blocks.find(
|
||
(block) => block.id === "default-info-ack",
|
||
);
|
||
assert.ok(
|
||
upgradedInfoAck,
|
||
"legacy upgrade should backfill default-info-ack block",
|
||
);
|
||
assert.equal(upgradedInfoAck.role, "assistant");
|
||
assert.equal(upgradedLegacyDefault.blocks[14].id, "default-format");
|
||
assert.equal(upgradedLegacyDefault.blocks[15].id, "default-rules");
|
||
assert.equal(upgradedLegacyDefault.blocks[14].content, "保留我自己的输出格式");
|
||
assert.equal(upgradedLegacyDefault.blocks[15].content, "保留我自己的行为规则");
|
||
assert.equal(upgradedLegacyDefault.blocks[14].role, "user");
|
||
assert.equal(upgradedLegacyDefault.blocks[15].role, "user");
|
||
|
||
const currentDefaults = createDefaultTaskProfiles();
|
||
const currentDefaultExtract = currentDefaults.extract.profiles[0];
|
||
|
||
const staleBuiltinDefaults = ensureTaskProfiles({
|
||
taskProfilesVersion: 3,
|
||
taskProfiles: {
|
||
extract: {
|
||
activeProfileId: "default",
|
||
profiles: [
|
||
{
|
||
...currentDefaultExtract,
|
||
updatedAt: "2000-01-01T00:00:00.000Z",
|
||
blocks: currentDefaultExtract.blocks.map((block) =>
|
||
block.id === "default-role"
|
||
? { ...block, content: "这是过期的默认角色定义" }
|
||
: block,
|
||
),
|
||
metadata: {
|
||
...(currentDefaultExtract.metadata || {}),
|
||
defaultTemplateVersion:
|
||
Number(currentDefaultExtract.metadata?.defaultTemplateVersion || 3),
|
||
defaultTemplateUpdatedAt: "2000-01-01T00:00:00.000Z",
|
||
},
|
||
},
|
||
{
|
||
id: "extract-custom-1",
|
||
taskType: "extract",
|
||
builtin: false,
|
||
name: "我的自定义预设",
|
||
promptMode: "block-based",
|
||
enabled: true,
|
||
updatedAt: "2026-04-05T00:00:00.000Z",
|
||
blocks: [
|
||
{
|
||
id: "custom-block-1",
|
||
name: "自定义块",
|
||
type: "custom",
|
||
enabled: true,
|
||
role: "system",
|
||
sourceKey: "",
|
||
sourceField: "",
|
||
content: "保留我的自定义内容",
|
||
injectionMode: "append",
|
||
order: 0,
|
||
},
|
||
],
|
||
generation: { ...(currentDefaultExtract.generation || {}) },
|
||
regex: {
|
||
...(currentDefaultExtract.regex || {}),
|
||
localRules: [],
|
||
},
|
||
metadata: {
|
||
note: "custom-profile-should-stay",
|
||
},
|
||
},
|
||
],
|
||
},
|
||
},
|
||
});
|
||
const refreshedDefaultExtract = staleBuiltinDefaults.extract.profiles.find(
|
||
(profile) => profile.id === "default",
|
||
);
|
||
const preservedCustomExtract = staleBuiltinDefaults.extract.profiles.find(
|
||
(profile) => profile.id === "extract-custom-1",
|
||
);
|
||
|
||
assert.ok(refreshedDefaultExtract);
|
||
assert.equal(
|
||
refreshedDefaultExtract.blocks.find((block) => block.id === "default-role")
|
||
?.content,
|
||
currentDefaultExtract.blocks.find((block) => block.id === "default-role")
|
||
?.content,
|
||
);
|
||
assert.equal(
|
||
refreshedDefaultExtract.metadata.defaultTemplateUpdatedAt,
|
||
currentDefaultExtract.metadata.defaultTemplateUpdatedAt,
|
||
);
|
||
assert.equal(
|
||
refreshedDefaultExtract.metadata.defaultTemplateFingerprint,
|
||
currentDefaultExtract.metadata.defaultTemplateFingerprint,
|
||
);
|
||
assert.match(
|
||
refreshedDefaultExtract.blocks.find((block) => block.id === "default-format")
|
||
?.content || "",
|
||
/cognitionUpdates/,
|
||
);
|
||
assert.ok(preservedCustomExtract);
|
||
assert.equal(
|
||
preservedCustomExtract.blocks[0].content,
|
||
"保留我的自定义内容",
|
||
);
|
||
|
||
const sameStampBuiltinDefault = ensureTaskProfiles({
|
||
taskProfilesVersion: 3,
|
||
taskProfiles: {
|
||
extract: {
|
||
activeProfileId: "default",
|
||
profiles: [
|
||
{
|
||
...currentDefaultExtract,
|
||
blocks: currentDefaultExtract.blocks.map((block) =>
|
||
block.id === "default-role"
|
||
? { ...block, content: "同版本下保留我的默认预设修改" }
|
||
: block,
|
||
),
|
||
metadata: {
|
||
...(currentDefaultExtract.metadata || {}),
|
||
},
|
||
},
|
||
],
|
||
},
|
||
},
|
||
});
|
||
const sameStampDefaultExtract = sameStampBuiltinDefault.extract.profiles.find(
|
||
(profile) => profile.id === "default",
|
||
);
|
||
assert.equal(
|
||
sameStampDefaultExtract.blocks.find((block) => block.id === "default-role")
|
||
?.content,
|
||
"同版本下保留我的默认预设修改",
|
||
);
|
||
|
||
const sameTimestampButChangedTemplateDefaults = ensureTaskProfiles({
|
||
taskProfilesVersion: 3,
|
||
taskProfiles: {
|
||
extract: {
|
||
activeProfileId: "default",
|
||
profiles: [
|
||
{
|
||
...currentDefaultExtract,
|
||
blocks: currentDefaultExtract.blocks.map((block) =>
|
||
block.id === "default-role"
|
||
? { ...block, content: "老模板内容但时间戳没变" }
|
||
: block,
|
||
),
|
||
metadata: {
|
||
...(currentDefaultExtract.metadata || {}),
|
||
defaultTemplateFingerprint: "fnv1a-deadbeef",
|
||
},
|
||
},
|
||
],
|
||
},
|
||
},
|
||
});
|
||
const fingerprintRefreshedDefault =
|
||
sameTimestampButChangedTemplateDefaults.extract.profiles.find(
|
||
(profile) => profile.id === "default",
|
||
);
|
||
assert.equal(
|
||
fingerprintRefreshedDefault.blocks.find(
|
||
(block) => block.id === "default-role",
|
||
)?.content,
|
||
currentDefaultExtract.blocks.find((block) => block.id === "default-role")
|
||
?.content,
|
||
);
|
||
|
||
assert.deepEqual(
|
||
upgradedLegacyDefault.blocks
|
||
.slice(7, 13)
|
||
.map((block) => block.sourceKey),
|
||
[
|
||
"graphStats",
|
||
"schema",
|
||
"activeSummaries",
|
||
"storyTimeContext",
|
||
"currentRange",
|
||
"recentMessages",
|
||
],
|
||
);
|
||
assert.ok(
|
||
upgradedLegacyDefault.blocks
|
||
.slice(0, 2)
|
||
.every((block) => block.role === "system"),
|
||
"heading / role 头部块应保持 system 角色",
|
||
);
|
||
assert.equal(upgradedLegacyDefault.blocks[2].id, "default-identity-ack");
|
||
assert.equal(upgradedLegacyDefault.blocks[2].role, "assistant");
|
||
assert.ok(
|
||
upgradedLegacyDefault.blocks
|
||
.slice(3, 13)
|
||
.every((block) => block.role === "system"),
|
||
"参考材料与本轮输入块应为 system 角色",
|
||
);
|
||
assert.equal(upgradedLegacyDefault.blocks[13].id, "default-info-ack");
|
||
assert.equal(upgradedLegacyDefault.blocks[13].role, "assistant");
|
||
|
||
const legacyRegexSettings = {
|
||
taskProfilesVersion: 3,
|
||
taskProfiles: createDefaultTaskProfiles(),
|
||
};
|
||
legacyRegexSettings.taskProfiles.extract.activeProfileId = "default";
|
||
legacyRegexSettings.taskProfiles.extract.profiles.push(
|
||
normalizeTaskProfile("extract", {
|
||
id: "extract-legacy-regex",
|
||
taskType: "extract",
|
||
name: "旧正则副本",
|
||
builtin: false,
|
||
regex: {
|
||
enabled: true,
|
||
inheritStRegex: true,
|
||
localRules: [
|
||
{
|
||
id: "legacy-rule-1",
|
||
script_name: "隐藏规则",
|
||
enabled: true,
|
||
find_regex: "/SECRET/g",
|
||
replace_string: "MASK",
|
||
},
|
||
],
|
||
},
|
||
}),
|
||
);
|
||
const migratedLegacyRegex = migratePerTaskRegexToGlobal(legacyRegexSettings);
|
||
assert.equal(migratedLegacyRegex.changed, true);
|
||
assert.equal(migratedLegacyRegex.settings.globalTaskRegex.enabled, true);
|
||
assert.deepEqual(
|
||
migratedLegacyRegex.settings.globalTaskRegex.localRules.map((rule) => rule.script_name),
|
||
[
|
||
"默认清理:thinking/analysis/reasoning",
|
||
"默认清理:choice",
|
||
"默认清理:UpdateVariable",
|
||
"默认清理:status_current_variable",
|
||
"默认清理:StatusPlaceHolderImpl",
|
||
"隐藏规则",
|
||
],
|
||
);
|
||
assert.deepEqual(
|
||
migratedLegacyRegex.settings.taskProfiles.extract.profiles.find(
|
||
(profile) => profile.id === "extract-legacy-regex",
|
||
)?.regex?.localRules || [],
|
||
[],
|
||
);
|
||
|
||
const existingGlobalRegexSettings = {
|
||
taskProfilesVersion: 3,
|
||
globalTaskRegex: {
|
||
enabled: true,
|
||
inheritStRegex: true,
|
||
sources: {
|
||
global: true,
|
||
preset: true,
|
||
character: true,
|
||
},
|
||
stages: {
|
||
"input.userMessage": true,
|
||
"input.recentMessages": true,
|
||
},
|
||
localRules: [
|
||
{
|
||
id: "existing-global-rule",
|
||
script_name: "现有通用规则",
|
||
enabled: true,
|
||
find_regex: "/GLOBAL/g",
|
||
replace_string: "KEEP",
|
||
},
|
||
],
|
||
},
|
||
taskProfiles: createDefaultTaskProfiles(),
|
||
};
|
||
existingGlobalRegexSettings.taskProfiles.extract.profiles.push(
|
||
normalizeTaskProfile("extract", {
|
||
id: "extract-legacy-extra",
|
||
taskType: "extract",
|
||
name: "旧规则补充",
|
||
builtin: false,
|
||
regex: {
|
||
localRules: [
|
||
{
|
||
id: "legacy-extra-rule",
|
||
script_name: "额外旧规则",
|
||
enabled: true,
|
||
find_regex: "/EXTRA/g",
|
||
replace_string: "ADD",
|
||
},
|
||
],
|
||
},
|
||
}),
|
||
);
|
||
const migratedWithExistingGlobal = migratePerTaskRegexToGlobal(
|
||
existingGlobalRegexSettings,
|
||
);
|
||
assert.equal(migratedWithExistingGlobal.settings.globalTaskRegex.enabled, true);
|
||
assert.deepEqual(
|
||
migratedWithExistingGlobal.settings.globalTaskRegex.localRules.map(
|
||
(rule) => rule.script_name,
|
||
),
|
||
["现有通用规则", "额外旧规则"],
|
||
);
|
||
|
||
const importedLegacyProfileMigration = migrateLegacyProfileRegexToGlobal(
|
||
{
|
||
enabled: true,
|
||
inheritStRegex: true,
|
||
sources: {
|
||
global: true,
|
||
preset: true,
|
||
character: true,
|
||
},
|
||
stages: {
|
||
"input.userMessage": true,
|
||
"input.recentMessages": true,
|
||
},
|
||
localRules: [],
|
||
},
|
||
{
|
||
taskType: "extract",
|
||
regex: {
|
||
enabled: false,
|
||
inheritStRegex: false,
|
||
sources: {
|
||
global: false,
|
||
preset: false,
|
||
character: false,
|
||
},
|
||
stages: {
|
||
"input.userMessage": false,
|
||
},
|
||
localRules: [
|
||
{
|
||
id: "legacy-import-rule",
|
||
script_name: "旧导入规则",
|
||
enabled: true,
|
||
find_regex: "/A/g",
|
||
replace_string: "B",
|
||
},
|
||
],
|
||
},
|
||
},
|
||
{
|
||
applyLegacyConfig: true,
|
||
},
|
||
);
|
||
assert.equal(importedLegacyProfileMigration.appliedLegacyConfig, true);
|
||
assert.equal(importedLegacyProfileMigration.globalTaskRegex.enabled, false);
|
||
assert.equal(
|
||
importedLegacyProfileMigration.globalTaskRegex.inheritStRegex,
|
||
false,
|
||
);
|
||
assert.equal(
|
||
importedLegacyProfileMigration.globalTaskRegex.sources.global,
|
||
false,
|
||
);
|
||
assert.equal(
|
||
importedLegacyProfileMigration.globalTaskRegex.stages["input.userMessage"],
|
||
false,
|
||
);
|
||
assert.deepEqual(
|
||
importedLegacyProfileMigration.globalTaskRegex.localRules.map(
|
||
(rule) => rule.script_name,
|
||
),
|
||
["旧导入规则"],
|
||
);
|
||
assert.deepEqual(
|
||
importedLegacyProfileMigration.profile?.regex || {},
|
||
{},
|
||
);
|
||
|
||
console.log("task-profile-migration tests passed");
|