mirror of
https://github.com/Youzini-afk/ST-Bionic-Memory-Ecology.git
synced 2026-05-15 14:20:35 +08:00
Add global task regex migration and UI
This commit is contained in:
6
index.js
6
index.js
@@ -146,6 +146,7 @@ import {
|
||||
} from "./ui/panel-bridge.js";
|
||||
import {
|
||||
migrateLegacyTaskProfiles,
|
||||
migratePerTaskRegexToGlobal,
|
||||
} from "./prompting/prompt-profiles.js";
|
||||
import { inspectTaskRegexReuse } from "./prompting/task-regex.js";
|
||||
import {
|
||||
@@ -2885,6 +2886,11 @@ function getSettings() {
|
||||
const migrated = migrateLegacyTaskProfiles(mergedSettings);
|
||||
mergedSettings.taskProfilesVersion = migrated.taskProfilesVersion;
|
||||
mergedSettings.taskProfiles = migrated.taskProfiles;
|
||||
const regexMigration = migratePerTaskRegexToGlobal(mergedSettings);
|
||||
if (regexMigration.changed) {
|
||||
mergedSettings.globalTaskRegex = regexMigration.settings.globalTaskRegex;
|
||||
mergedSettings.taskProfiles = regexMigration.settings.taskProfiles;
|
||||
}
|
||||
extension_settings[MODULE_NAME] = mergedSettings;
|
||||
globalThis.__stBmeDebugLoggingEnabled = Boolean(
|
||||
mergedSettings.debugLoggingEnabled,
|
||||
|
||||
@@ -806,6 +806,71 @@ export function normalizeTaskRegexStages(stages = {}) {
|
||||
return normalized;
|
||||
}
|
||||
|
||||
export function createDefaultGlobalTaskRegex() {
|
||||
return {
|
||||
enabled: true,
|
||||
inheritStRegex: true,
|
||||
sources: {
|
||||
global: true,
|
||||
preset: true,
|
||||
character: true,
|
||||
},
|
||||
stages: normalizeTaskRegexStages(DEFAULT_TASK_REGEX_STAGES),
|
||||
localRules: [],
|
||||
};
|
||||
}
|
||||
|
||||
export function dedupeRegexRules(rules = [], taskType = "task") {
|
||||
const sourceRules = Array.isArray(rules) ? rules : [];
|
||||
const deduped = [];
|
||||
const seen = new Set();
|
||||
|
||||
for (let index = 0; index < sourceRules.length; index++) {
|
||||
const normalized = normalizeRegexLocalRule(sourceRules[index], taskType, index);
|
||||
const key = JSON.stringify({
|
||||
enabled: normalized.enabled !== false,
|
||||
find_regex: normalized.find_regex,
|
||||
replace_string: normalized.replace_string,
|
||||
trim_strings: normalized.trim_strings,
|
||||
source: {
|
||||
user_input: normalized.source?.user_input !== false,
|
||||
ai_output: normalized.source?.ai_output !== false,
|
||||
},
|
||||
destination: {
|
||||
prompt: normalized.destination?.prompt !== false,
|
||||
display: Boolean(normalized.destination?.display),
|
||||
},
|
||||
min_depth: normalized.min_depth,
|
||||
max_depth: normalized.max_depth,
|
||||
});
|
||||
if (seen.has(key)) continue;
|
||||
seen.add(key);
|
||||
deduped.push(normalized);
|
||||
}
|
||||
|
||||
return deduped;
|
||||
}
|
||||
|
||||
export function normalizeGlobalTaskRegex(config = {}, taskType = "global") {
|
||||
const defaults = createDefaultGlobalTaskRegex();
|
||||
const source =
|
||||
config && typeof config === "object" && !Array.isArray(config) ? config : {};
|
||||
|
||||
return {
|
||||
enabled: source.enabled !== false,
|
||||
inheritStRegex: source.inheritStRegex !== false,
|
||||
sources: {
|
||||
...defaults.sources,
|
||||
...(source.sources && typeof source.sources === "object" ? source.sources : {}),
|
||||
},
|
||||
stages: {
|
||||
...normalizeTaskRegexStages(defaults.stages),
|
||||
...normalizeTaskRegexStages(source.stages || {}),
|
||||
},
|
||||
localRules: dedupeRegexRules(source.localRules, taskType),
|
||||
};
|
||||
}
|
||||
|
||||
export function isTaskRegexStageEnabled(stages = {}, stageKey = "") {
|
||||
const normalizedStages = normalizeTaskRegexStages(stages);
|
||||
const normalizedStageKey = normalizeRegexStageKey(stageKey);
|
||||
@@ -829,6 +894,20 @@ export function isTaskRegexStageEnabled(stages = {}, stageKey = "") {
|
||||
return normalizedStages[normalizedStageKey] !== false;
|
||||
}
|
||||
|
||||
function buildRegexConfigSignature(config = {}, taskType = "global") {
|
||||
const normalized = normalizeGlobalTaskRegex(config, taskType);
|
||||
return JSON.stringify({
|
||||
enabled: normalized.enabled !== false,
|
||||
inheritStRegex: normalized.inheritStRegex !== false,
|
||||
sources: {
|
||||
global: normalized.sources?.global !== false,
|
||||
preset: normalized.sources?.preset !== false,
|
||||
character: normalized.sources?.character !== false,
|
||||
},
|
||||
stages: normalizeTaskRegexStages(normalized.stages || {}),
|
||||
});
|
||||
}
|
||||
|
||||
function normalizeTaskProfilesState(taskProfiles = {}) {
|
||||
return ensureTaskProfiles({ taskProfiles });
|
||||
}
|
||||
@@ -1358,6 +1437,141 @@ export function migrateLegacyTaskProfiles(settings = {}) {
|
||||
};
|
||||
}
|
||||
|
||||
export function migratePerTaskRegexToGlobal(settings = {}) {
|
||||
const taskProfiles = ensureTaskProfiles(settings);
|
||||
const defaultGlobalRegex = normalizeGlobalTaskRegex(
|
||||
createDefaultGlobalTaskRegex(),
|
||||
"global",
|
||||
);
|
||||
const existingGlobalRegex = normalizeGlobalTaskRegex(
|
||||
settings.globalTaskRegex || {},
|
||||
"global",
|
||||
);
|
||||
const existingGlobalConfigSignature = buildRegexConfigSignature(
|
||||
existingGlobalRegex,
|
||||
"global",
|
||||
);
|
||||
const defaultGlobalConfigSignature = buildRegexConfigSignature(
|
||||
defaultGlobalRegex,
|
||||
"global",
|
||||
);
|
||||
const profilesWithLegacyRegex = [];
|
||||
|
||||
for (const taskType of TASK_TYPES) {
|
||||
const bucket = taskProfiles[taskType];
|
||||
const defaultProfileRegex = normalizeGlobalTaskRegex(
|
||||
createDefaultTaskProfile(taskType).regex || {},
|
||||
taskType,
|
||||
);
|
||||
const defaultProfileConfigSignature = buildRegexConfigSignature(
|
||||
defaultProfileRegex,
|
||||
taskType,
|
||||
);
|
||||
|
||||
for (const profile of Array.isArray(bucket?.profiles) ? bucket.profiles : []) {
|
||||
const normalizedProfileRegex = normalizeGlobalTaskRegex(
|
||||
profile?.regex || {},
|
||||
taskType,
|
||||
);
|
||||
const profileConfigSignature = buildRegexConfigSignature(
|
||||
normalizedProfileRegex,
|
||||
taskType,
|
||||
);
|
||||
const hasRules = normalizedProfileRegex.localRules.length > 0;
|
||||
const hasConfigDiff = profileConfigSignature !== defaultProfileConfigSignature;
|
||||
if (!hasRules && !hasConfigDiff) continue;
|
||||
profilesWithLegacyRegex.push({
|
||||
taskType,
|
||||
profileId: String(profile?.id || ""),
|
||||
regex: normalizedProfileRegex,
|
||||
configSignature: profileConfigSignature,
|
||||
hasConfigDiff,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (profilesWithLegacyRegex.length === 0) {
|
||||
return {
|
||||
changed: false,
|
||||
settings: {
|
||||
...settings,
|
||||
taskProfiles,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const configCandidates = profilesWithLegacyRegex.filter(
|
||||
(item) => item.hasConfigDiff,
|
||||
);
|
||||
const uniqueCandidateSignatures = [
|
||||
...new Set(configCandidates.map((item) => item.configSignature)),
|
||||
];
|
||||
if (uniqueCandidateSignatures.length > 1) {
|
||||
console.warn(
|
||||
"[ST-BME] 检测到多个任务预设存在冲突的旧正则配置,已按顺序采用第一份并统一迁移。",
|
||||
configCandidates.map((item) => ({
|
||||
taskType: item.taskType,
|
||||
profileId: item.profileId,
|
||||
})),
|
||||
);
|
||||
}
|
||||
|
||||
const selectedConfig =
|
||||
existingGlobalConfigSignature !== defaultGlobalConfigSignature
|
||||
? existingGlobalRegex
|
||||
: configCandidates[0]?.regex || defaultGlobalRegex;
|
||||
|
||||
const mergedLocalRules = dedupeRegexRules(
|
||||
[
|
||||
...(Array.isArray(existingGlobalRegex.localRules)
|
||||
? existingGlobalRegex.localRules
|
||||
: []),
|
||||
...profilesWithLegacyRegex.flatMap((item) =>
|
||||
Array.isArray(item.regex?.localRules) ? item.regex.localRules : [],
|
||||
),
|
||||
],
|
||||
"global",
|
||||
);
|
||||
|
||||
const nextGlobalRegex = {
|
||||
...normalizeGlobalTaskRegex(selectedConfig, "global"),
|
||||
localRules: mergedLocalRules,
|
||||
};
|
||||
|
||||
const nextTaskProfiles = {};
|
||||
for (const taskType of TASK_TYPES) {
|
||||
const bucket = taskProfiles[taskType] || {
|
||||
activeProfileId: DEFAULT_PROFILE_ID,
|
||||
profiles: [createDefaultTaskProfile(taskType)],
|
||||
};
|
||||
const legacyProfileIds = new Set(
|
||||
profilesWithLegacyRegex
|
||||
.filter((item) => item.taskType === taskType)
|
||||
.map((item) => item.profileId),
|
||||
);
|
||||
nextTaskProfiles[taskType] = {
|
||||
...bucket,
|
||||
profiles: (Array.isArray(bucket.profiles) ? bucket.profiles : []).map((profile) =>
|
||||
legacyProfileIds.has(String(profile?.id || ""))
|
||||
? normalizeTaskProfile(taskType, {
|
||||
...profile,
|
||||
regex: {},
|
||||
})
|
||||
: normalizeTaskProfile(taskType, profile),
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
changed: true,
|
||||
settings: {
|
||||
...settings,
|
||||
globalTaskRegex: nextGlobalRegex,
|
||||
taskProfiles: nextTaskProfiles,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function getActiveTaskProfile(settings = {}, taskType) {
|
||||
const taskProfiles = ensureTaskProfiles(settings);
|
||||
const bucket = taskProfiles?.[taskType];
|
||||
|
||||
@@ -8,6 +8,7 @@ import { getHostAdapter } from "../host/adapter/index.js";
|
||||
import {
|
||||
getActiveTaskProfile,
|
||||
isTaskRegexStageEnabled,
|
||||
normalizeGlobalTaskRegex,
|
||||
normalizeTaskRegexStages,
|
||||
} from "./prompt-profiles.js";
|
||||
|
||||
@@ -1026,6 +1027,29 @@ function applyHostRegexReuseFallback(
|
||||
};
|
||||
}
|
||||
|
||||
function resolveTaskRegexConfig(settings = {}, taskType = "") {
|
||||
const hasGlobalRegex =
|
||||
settings?.globalTaskRegex &&
|
||||
typeof settings.globalTaskRegex === "object" &&
|
||||
!Array.isArray(settings.globalTaskRegex);
|
||||
|
||||
if (hasGlobalRegex) {
|
||||
return {
|
||||
profile: null,
|
||||
regexConfig: normalizeGlobalTaskRegex(
|
||||
settings.globalTaskRegex || {},
|
||||
"global",
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
const profile = getActiveTaskProfile(settings, taskType);
|
||||
return {
|
||||
profile,
|
||||
regexConfig: normalizeGlobalTaskRegex(profile?.regex || {}, taskType || "task"),
|
||||
};
|
||||
}
|
||||
|
||||
export function applyHostRegexReuse(
|
||||
settings = {},
|
||||
taskType,
|
||||
@@ -1041,8 +1065,7 @@ export function applyHostRegexReuse(
|
||||
const normalizedTaskType = String(taskType || "").trim();
|
||||
const normalizedSourceType = normalizeHostRegexSourceType(sourceType);
|
||||
const normalizedFormatterOptions = normalizeHostFormatterOptions(formatterOptions);
|
||||
const profile = getActiveTaskProfile(settings, normalizedTaskType);
|
||||
const regexConfig = profile?.regex || {};
|
||||
const { regexConfig } = resolveTaskRegexConfig(settings, taskType);
|
||||
const regexHost = getRegexHost();
|
||||
const executionState = buildHostRegexExecutionState(regexHost);
|
||||
|
||||
@@ -1193,8 +1216,7 @@ export function applyTaskRegex(
|
||||
debugCollector = null,
|
||||
role = "system",
|
||||
) {
|
||||
const profile = getActiveTaskProfile(settings, taskType);
|
||||
const regexConfig = profile?.regex || {};
|
||||
const { regexConfig } = resolveTaskRegexConfig(settings, taskType);
|
||||
const input = typeof text === "string" ? text : "";
|
||||
|
||||
if (!regexConfig.enabled) {
|
||||
@@ -1252,8 +1274,7 @@ export function applyTaskRegex(
|
||||
}
|
||||
|
||||
export function inspectTaskRegexReuse(settings = {}, taskType = "") {
|
||||
const profile = getActiveTaskProfile(settings, taskType);
|
||||
const regexConfig = profile?.regex || {};
|
||||
const { profile, regexConfig } = resolveTaskRegexConfig(settings, taskType);
|
||||
const detailed = collectTavernRulesDetailed(regexConfig);
|
||||
const stageConfig = normalizeTaskRegexStages(regexConfig.stages || {});
|
||||
const localRules = collectLocalRules(regexConfig);
|
||||
@@ -1292,3 +1313,6 @@ export function inspectTaskRegexReuse(settings = {}, taskType = "") {
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
import { createDefaultTaskProfiles } from "../prompting/prompt-profiles.js";
|
||||
import {
|
||||
createDefaultGlobalTaskRegex,
|
||||
createDefaultTaskProfiles,
|
||||
} from "../prompting/prompt-profiles.js";
|
||||
|
||||
function clampIntValue(value, fallback = 0, min = 0, max = 9999) {
|
||||
const numeric = Number(value);
|
||||
@@ -110,6 +113,7 @@ export const defaultSettings = {
|
||||
reflectionPrompt: "",
|
||||
taskProfilesVersion: 3,
|
||||
taskProfiles: createDefaultTaskProfiles(),
|
||||
globalTaskRegex: createDefaultGlobalTaskRegex(),
|
||||
|
||||
// ====== v2 增强设置 ======
|
||||
enableConsolidation: true,
|
||||
|
||||
@@ -112,6 +112,10 @@ export function createGenerationRecallHarness(options = {}) {
|
||||
taskProfilesVersion: settings?.taskProfilesVersion || 0,
|
||||
taskProfiles: settings?.taskProfiles || {},
|
||||
}),
|
||||
migratePerTaskRegexToGlobal: (settings = {}) => ({
|
||||
changed: false,
|
||||
settings,
|
||||
}),
|
||||
refreshPanelLiveStateController: () => {
|
||||
context.refreshPanelCalls += 1;
|
||||
},
|
||||
|
||||
726
ui/panel.js
726
ui/panel.js
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user