mirror of
https://github.com/Youzini-afk/ST-Bionic-Memory-Ecology.git
synced 2026-05-15 22:30:38 +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";
|
} from "./ui/panel-bridge.js";
|
||||||
import {
|
import {
|
||||||
migrateLegacyTaskProfiles,
|
migrateLegacyTaskProfiles,
|
||||||
|
migratePerTaskRegexToGlobal,
|
||||||
} from "./prompting/prompt-profiles.js";
|
} from "./prompting/prompt-profiles.js";
|
||||||
import { inspectTaskRegexReuse } from "./prompting/task-regex.js";
|
import { inspectTaskRegexReuse } from "./prompting/task-regex.js";
|
||||||
import {
|
import {
|
||||||
@@ -2885,6 +2886,11 @@ function getSettings() {
|
|||||||
const migrated = migrateLegacyTaskProfiles(mergedSettings);
|
const migrated = migrateLegacyTaskProfiles(mergedSettings);
|
||||||
mergedSettings.taskProfilesVersion = migrated.taskProfilesVersion;
|
mergedSettings.taskProfilesVersion = migrated.taskProfilesVersion;
|
||||||
mergedSettings.taskProfiles = migrated.taskProfiles;
|
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;
|
extension_settings[MODULE_NAME] = mergedSettings;
|
||||||
globalThis.__stBmeDebugLoggingEnabled = Boolean(
|
globalThis.__stBmeDebugLoggingEnabled = Boolean(
|
||||||
mergedSettings.debugLoggingEnabled,
|
mergedSettings.debugLoggingEnabled,
|
||||||
|
|||||||
@@ -806,6 +806,71 @@ export function normalizeTaskRegexStages(stages = {}) {
|
|||||||
return normalized;
|
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 = "") {
|
export function isTaskRegexStageEnabled(stages = {}, stageKey = "") {
|
||||||
const normalizedStages = normalizeTaskRegexStages(stages);
|
const normalizedStages = normalizeTaskRegexStages(stages);
|
||||||
const normalizedStageKey = normalizeRegexStageKey(stageKey);
|
const normalizedStageKey = normalizeRegexStageKey(stageKey);
|
||||||
@@ -829,6 +894,20 @@ export function isTaskRegexStageEnabled(stages = {}, stageKey = "") {
|
|||||||
return normalizedStages[normalizedStageKey] !== false;
|
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 = {}) {
|
function normalizeTaskProfilesState(taskProfiles = {}) {
|
||||||
return ensureTaskProfiles({ 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) {
|
export function getActiveTaskProfile(settings = {}, taskType) {
|
||||||
const taskProfiles = ensureTaskProfiles(settings);
|
const taskProfiles = ensureTaskProfiles(settings);
|
||||||
const bucket = taskProfiles?.[taskType];
|
const bucket = taskProfiles?.[taskType];
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import { getHostAdapter } from "../host/adapter/index.js";
|
|||||||
import {
|
import {
|
||||||
getActiveTaskProfile,
|
getActiveTaskProfile,
|
||||||
isTaskRegexStageEnabled,
|
isTaskRegexStageEnabled,
|
||||||
|
normalizeGlobalTaskRegex,
|
||||||
normalizeTaskRegexStages,
|
normalizeTaskRegexStages,
|
||||||
} from "./prompt-profiles.js";
|
} 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(
|
export function applyHostRegexReuse(
|
||||||
settings = {},
|
settings = {},
|
||||||
taskType,
|
taskType,
|
||||||
@@ -1041,8 +1065,7 @@ export function applyHostRegexReuse(
|
|||||||
const normalizedTaskType = String(taskType || "").trim();
|
const normalizedTaskType = String(taskType || "").trim();
|
||||||
const normalizedSourceType = normalizeHostRegexSourceType(sourceType);
|
const normalizedSourceType = normalizeHostRegexSourceType(sourceType);
|
||||||
const normalizedFormatterOptions = normalizeHostFormatterOptions(formatterOptions);
|
const normalizedFormatterOptions = normalizeHostFormatterOptions(formatterOptions);
|
||||||
const profile = getActiveTaskProfile(settings, normalizedTaskType);
|
const { regexConfig } = resolveTaskRegexConfig(settings, taskType);
|
||||||
const regexConfig = profile?.regex || {};
|
|
||||||
const regexHost = getRegexHost();
|
const regexHost = getRegexHost();
|
||||||
const executionState = buildHostRegexExecutionState(regexHost);
|
const executionState = buildHostRegexExecutionState(regexHost);
|
||||||
|
|
||||||
@@ -1193,8 +1216,7 @@ export function applyTaskRegex(
|
|||||||
debugCollector = null,
|
debugCollector = null,
|
||||||
role = "system",
|
role = "system",
|
||||||
) {
|
) {
|
||||||
const profile = getActiveTaskProfile(settings, taskType);
|
const { regexConfig } = resolveTaskRegexConfig(settings, taskType);
|
||||||
const regexConfig = profile?.regex || {};
|
|
||||||
const input = typeof text === "string" ? text : "";
|
const input = typeof text === "string" ? text : "";
|
||||||
|
|
||||||
if (!regexConfig.enabled) {
|
if (!regexConfig.enabled) {
|
||||||
@@ -1252,8 +1274,7 @@ export function applyTaskRegex(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function inspectTaskRegexReuse(settings = {}, taskType = "") {
|
export function inspectTaskRegexReuse(settings = {}, taskType = "") {
|
||||||
const profile = getActiveTaskProfile(settings, taskType);
|
const { profile, regexConfig } = resolveTaskRegexConfig(settings, taskType);
|
||||||
const regexConfig = profile?.regex || {};
|
|
||||||
const detailed = collectTavernRulesDetailed(regexConfig);
|
const detailed = collectTavernRulesDetailed(regexConfig);
|
||||||
const stageConfig = normalizeTaskRegexStages(regexConfig.stages || {});
|
const stageConfig = normalizeTaskRegexStages(regexConfig.stages || {});
|
||||||
const localRules = collectLocalRules(regexConfig);
|
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) {
|
function clampIntValue(value, fallback = 0, min = 0, max = 9999) {
|
||||||
const numeric = Number(value);
|
const numeric = Number(value);
|
||||||
@@ -110,6 +113,7 @@ export const defaultSettings = {
|
|||||||
reflectionPrompt: "",
|
reflectionPrompt: "",
|
||||||
taskProfilesVersion: 3,
|
taskProfilesVersion: 3,
|
||||||
taskProfiles: createDefaultTaskProfiles(),
|
taskProfiles: createDefaultTaskProfiles(),
|
||||||
|
globalTaskRegex: createDefaultGlobalTaskRegex(),
|
||||||
|
|
||||||
// ====== v2 增强设置 ======
|
// ====== v2 增强设置 ======
|
||||||
enableConsolidation: true,
|
enableConsolidation: true,
|
||||||
|
|||||||
@@ -112,6 +112,10 @@ export function createGenerationRecallHarness(options = {}) {
|
|||||||
taskProfilesVersion: settings?.taskProfilesVersion || 0,
|
taskProfilesVersion: settings?.taskProfilesVersion || 0,
|
||||||
taskProfiles: settings?.taskProfiles || {},
|
taskProfiles: settings?.taskProfiles || {},
|
||||||
}),
|
}),
|
||||||
|
migratePerTaskRegexToGlobal: (settings = {}) => ({
|
||||||
|
changed: false,
|
||||||
|
settings,
|
||||||
|
}),
|
||||||
refreshPanelLiveStateController: () => {
|
refreshPanelLiveStateController: () => {
|
||||||
context.refreshPanelCalls += 1;
|
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