diff --git a/index.js b/index.js index d4b5187..309b1da 100644 --- a/index.js +++ b/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, diff --git a/prompting/prompt-profiles.js b/prompting/prompt-profiles.js index d3f8f69..96c45c2 100644 --- a/prompting/prompt-profiles.js +++ b/prompting/prompt-profiles.js @@ -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]; diff --git a/prompting/task-regex.js b/prompting/task-regex.js index 8242946..16749a7 100644 --- a/prompting/task-regex.js +++ b/prompting/task-regex.js @@ -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 = "") { ), }; } + + + diff --git a/runtime/settings-defaults.js b/runtime/settings-defaults.js index 970399f..3c994f7 100644 --- a/runtime/settings-defaults.js +++ b/runtime/settings-defaults.js @@ -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, diff --git a/tests/helpers/generation-recall-harness.mjs b/tests/helpers/generation-recall-harness.mjs index 560ca0c..a4b37fa 100644 --- a/tests/helpers/generation-recall-harness.mjs +++ b/tests/helpers/generation-recall-harness.mjs @@ -112,6 +112,10 @@ export function createGenerationRecallHarness(options = {}) { taskProfilesVersion: settings?.taskProfilesVersion || 0, taskProfiles: settings?.taskProfiles || {}, }), + migratePerTaskRegexToGlobal: (settings = {}) => ({ + changed: false, + settings, + }), refreshPanelLiveStateController: () => { context.refreshPanelCalls += 1; }, diff --git a/ui/panel.js b/ui/panel.js index 81e38d1..3a8946d 100644 --- a/ui/panel.js +++ b/ui/panel.js @@ -20,10 +20,12 @@ import { } from "../llm/llm-preset-utils.js"; import { cloneTaskProfile, + createDefaultGlobalTaskRegex, createBuiltinPromptBlock, createCustomPromptBlock, createLocalRegexRule, DEFAULT_TASK_BLOCKS, + dedupeRegexRules, ensureTaskProfiles, exportTaskProfile as serializeTaskProfile, getBuiltinBlockDefinitions, @@ -31,6 +33,7 @@ import { getTaskTypeOptions, importTaskProfile as parseImportedTaskProfile, isTaskRegexStageEnabled, + normalizeGlobalTaskRegex, normalizeTaskRegexStages, restoreDefaultTaskProfile, setActiveTaskProfileId, @@ -67,7 +70,6 @@ function getDefaultPromptText(taskType = "") { const TASK_PROFILE_TABS = [ { id: "generation", label: "生成参数" }, { id: "prompt", label: "Prompt 编排" }, - { id: "regex", label: "正则" }, { id: "debug", label: "调试预览" }, ]; @@ -226,6 +228,8 @@ let currentTaskProfileTaskType = "extract"; let currentTaskProfileTabId = "generation"; let currentTaskProfileBlockId = ""; let currentTaskProfileRuleId = ""; +let showGlobalRegexPanel = false; +let currentGlobalRegexRuleId = ""; let currentCognitionOwnerKey = ""; let currentGraphView = "graph"; let fetchedMemoryLLMModels = []; @@ -4784,16 +4788,58 @@ function _bindTaskProfileWorkspace() { try { const text = await file.text(); const settings = _getSettings?.() || {}; - const imported = parseImportedTaskProfile( - settings.taskProfiles || {}, - text, + const parsed = JSON.parse(text); + let nextGlobalTaskRegex = _normalizeGlobalRegexDraft( + settings.globalTaskRegex || {}, ); + const importedGlobalMerge = _mergeImportedGlobalRegex( + nextGlobalTaskRegex, + parsed?.globalTaskRegex, + ); + nextGlobalTaskRegex = importedGlobalMerge.globalTaskRegex; + let imported = parseImportedTaskProfile( + settings.taskProfiles || {}, + parsed, + ); + const legacyRuleMerge = _mergeProfileRegexRulesIntoGlobal( + nextGlobalTaskRegex, + imported.profile, + ); + nextGlobalTaskRegex = legacyRuleMerge.globalTaskRegex; + if (legacyRuleMerge.clearedLegacyRules) { + imported = { + ...imported, + profile: legacyRuleMerge.profile, + taskProfiles: upsertTaskProfile( + imported.taskProfiles, + imported.taskType, + legacyRuleMerge.profile, + { setActive: true }, + ), + }; + } currentTaskProfileTaskType = imported.taskType || currentTaskProfileTaskType; currentTaskProfileBlockId = imported.profile?.blocks?.[0]?.id || ""; currentTaskProfileRuleId = imported.profile?.regex?.localRules?.[0]?.id || ""; - _patchTaskProfiles(imported.taskProfiles); - toastr.success("预设导入成功", "ST-BME"); + _patchSettings( + { + taskProfilesVersion: 3, + taskProfiles: imported.taskProfiles, + globalTaskRegex: nextGlobalTaskRegex, + }, + { + refreshTaskWorkspace: true, + }, + ); + const mergedRuleCount = + importedGlobalMerge.mergedRuleCount + legacyRuleMerge.mergedRuleCount; + toastr.success( + mergedRuleCount > 0 + ? `预设导入成功,${mergedRuleCount} 条正则规则已合并到通用正则规则` + : "预设导入成功", + "ST-BME", + ); } catch (error) { console.error("[ST-BME] 导入任务预设失败:", error); toastr.error(`预设导入失败: ${error?.message || error}`, "ST-BME"); @@ -4817,14 +4863,41 @@ function _bindTaskProfileWorkspace() { } const settings = _getSettings?.() || {}; let mergedProfiles = settings.taskProfiles || {}; + let nextGlobalTaskRegex = _normalizeGlobalRegexDraft( + settings.globalTaskRegex || {}, + ); + const importedGlobalMerge = _mergeImportedGlobalRegex( + nextGlobalTaskRegex, + parsed?.globalTaskRegex, + ); + nextGlobalTaskRegex = importedGlobalMerge.globalTaskRegex; let importedCount = 0; + let mergedLegacyRuleCount = 0; for (const [taskType, entry] of Object.entries(parsed.profiles)) { try { - const imported = parseImportedTaskProfile( + let imported = parseImportedTaskProfile( mergedProfiles, entry, taskType, ); + const legacyRuleMerge = _mergeProfileRegexRulesIntoGlobal( + nextGlobalTaskRegex, + imported.profile, + ); + nextGlobalTaskRegex = legacyRuleMerge.globalTaskRegex; + mergedLegacyRuleCount += legacyRuleMerge.mergedRuleCount; + if (legacyRuleMerge.clearedLegacyRules) { + imported = { + ...imported, + profile: legacyRuleMerge.profile, + taskProfiles: upsertTaskProfile( + imported.taskProfiles, + imported.taskType, + legacyRuleMerge.profile, + { setActive: true }, + ), + }; + } mergedProfiles = imported.taskProfiles; importedCount++; } catch (innerError) { @@ -4835,8 +4908,24 @@ function _bindTaskProfileWorkspace() { toastr.warning("没有成功导入任何预设", "ST-BME"); return; } - _patchTaskProfiles(mergedProfiles); - toastr.success(`已导入 ${importedCount} 个任务预设`, "ST-BME"); + _patchSettings( + { + taskProfilesVersion: 3, + taskProfiles: mergedProfiles, + globalTaskRegex: nextGlobalTaskRegex, + }, + { + refreshTaskWorkspace: true, + }, + ); + const mergedRuleCount = + importedGlobalMerge.mergedRuleCount + mergedLegacyRuleCount; + toastr.success( + mergedRuleCount > 0 + ? `已导入 ${importedCount} 个任务预设,并合并 ${mergedRuleCount} 条通用正则规则` + : `已导入 ${importedCount} 个任务预设`, + "ST-BME", + ); } catch (error) { console.error("[ST-BME] 导入全部预设失败:", error); toastr.error(`导入全部预设失败: ${error?.message || error}`, "ST-BME"); @@ -4851,6 +4940,7 @@ function _bindTaskProfileWorkspace() { function _handleTaskProfileWorkspaceInput(event) { const target = event.target; if (!(target instanceof HTMLElement)) return; + const isGlobalRegexPanel = _isGlobalRegexPanelTarget(target); if (target.matches("[data-block-field]")) { _persistSelectedBlockField(target, false); @@ -4880,13 +4970,18 @@ function _handleTaskProfileWorkspaceInput(event) { target.matches("[data-regex-rule-source]") || target.matches("[data-regex-rule-destination]") ) { - _persistSelectedRegexRuleField(target, false); + if (isGlobalRegexPanel) { + _persistSelectedGlobalRegexRuleField(target, false); + } else { + _persistSelectedRegexRuleField(target, false); + } } } function _handleTaskProfileWorkspaceChange(event) { const target = event.target; if (!(target instanceof HTMLElement)) return; + const isGlobalRegexPanel = _isGlobalRegexPanelTarget(target); if (target.id === "bme-task-profile-select") { const settings = _getSettings?.() || {}; @@ -4912,17 +5007,29 @@ function _handleTaskProfileWorkspaceChange(event) { } if (target.matches("[data-regex-field]")) { - _persistRegexConfigField(target, false); + if (isGlobalRegexPanel) { + _persistGlobalRegexField(target, false); + } else { + _persistRegexConfigField(target, false); + } return; } if (target.matches("[data-regex-source]")) { - _persistRegexSourceField(target, false); + if (isGlobalRegexPanel) { + _persistGlobalRegexSourceField(target, false); + } else { + _persistRegexSourceField(target, false); + } return; } if (target.matches("[data-regex-stage]")) { - _persistRegexStageField(target, false); + if (isGlobalRegexPanel) { + _persistGlobalRegexStageField(target, false); + } else { + _persistRegexStageField(target, false); + } return; } @@ -4931,12 +5038,20 @@ function _handleTaskProfileWorkspaceChange(event) { target.matches("[data-regex-rule-source]") || target.matches("[data-regex-rule-destination]") ) { - _persistSelectedRegexRuleField(target, true); + if (isGlobalRegexPanel) { + _persistSelectedGlobalRegexRuleField(target, true); + } else { + _persistSelectedRegexRuleField(target, true); + } } } function _getTaskProfileWorkspaceState(settings = _getSettings?.() || {}) { const taskProfiles = ensureTaskProfiles(settings); + const globalTaskRegex = _normalizeGlobalRegexDraft(settings.globalTaskRegex || {}); + const globalRegexRules = Array.isArray(globalTaskRegex.localRules) + ? globalTaskRegex.localRules + : []; const taskTypeOptions = getTaskTypeOptions(); const runtimeDebug = _getRuntimeDebugSnapshot?.() || { hostCapabilities: null, @@ -4970,10 +5085,16 @@ function _getTaskProfileWorkspaceState(settings = _getSettings?.() || {}) { if (!regexRules.some((rule) => rule.id === currentTaskProfileRuleId)) { currentTaskProfileRuleId = regexRules[0]?.id || ""; } + if (!globalRegexRules.some((rule) => rule.id === currentGlobalRegexRuleId)) { + currentGlobalRegexRuleId = globalRegexRules[0]?.id || ""; + } return { settings, taskProfiles, + globalTaskRegex, + globalRegexRules, + showGlobalRegex: showGlobalRegexPanel, taskTypeOptions, taskType: currentTaskProfileTaskType, taskTabId: currentTaskProfileTabId, @@ -4985,6 +5106,8 @@ function _getTaskProfileWorkspaceState(settings = _getSettings?.() || {}) { regexRules, selectedRule: regexRules.find((rule) => rule.id === currentTaskProfileRuleId) || null, + selectedGlobalRegexRule: + globalRegexRules.find((rule) => rule.id === currentGlobalRegexRuleId) || null, builtinBlockDefinitions: getBuiltinBlockDefinitions(), runtimeDebug, }; @@ -5636,6 +5759,10 @@ async function _handleTaskProfileWorkspaceClick(event) { currentTaskProfileRuleId = ""; _refreshTaskProfileWorkspace(); return; + case "toggle-global-regex": + showGlobalRegexPanel = !showGlobalRegexPanel; + _refreshTaskProfileWorkspace(); + return; case "switch-task-tab": currentTaskProfileTabId = actionEl.dataset.taskTab || currentTaskProfileTabId; @@ -5655,7 +5782,11 @@ async function _handleTaskProfileWorkspaceClick(event) { _refreshTaskProfileWorkspace(); return; case "select-regex-rule": - currentTaskProfileRuleId = actionEl.dataset.ruleId || ""; + if (_isGlobalRegexPanelTarget(actionEl)) { + currentGlobalRegexRuleId = actionEl.dataset.ruleId || ""; + } else { + currentTaskProfileRuleId = actionEl.dataset.ruleId || ""; + } _refreshTaskProfileWorkspace(); return; case "add-custom-block": @@ -5748,20 +5879,25 @@ async function _handleTaskProfileWorkspaceClick(event) { return; } case "export-profile": - _downloadTaskProfile(state.taskProfiles, currentTaskProfileTaskType, selectedProfile); + _downloadTaskProfile( + state.taskProfiles, + currentTaskProfileTaskType, + selectedProfile, + state.globalTaskRegex, + ); return; case "import-profile": document.getElementById("bme-task-profile-import")?.click(); return; case "export-all-profiles": - _downloadAllTaskProfiles(state.taskProfiles); + _downloadAllTaskProfiles(state.taskProfiles, state.globalTaskRegex); return; case "import-all-profiles": document.getElementById("bme-task-profile-import-all")?.click(); return; case "restore-all-profiles": { const confirmed = window.confirm( - "这会将全部 6 个任务的默认预设恢复为出厂状态。已保存的自定义预设不受影响。是否继续?", + "这会将全部 6 个任务的默认预设恢复为出厂状态。已保存的自定义预设不受影响,通用正则规则也不受影响。是否继续?", ); if (!confirmed) return; const taskTypes = getTaskTypeOptions().map((t) => t.id); @@ -5815,6 +5951,33 @@ async function _handleTaskProfileWorkspaceClick(event) { case "delete-regex-rule": _deleteRegexRule(actionEl.dataset.ruleId); return; + case "add-global-regex-rule": + _updateGlobalTaskRegex((draft) => { + const localRules = Array.isArray(draft.localRules) ? draft.localRules : []; + const nextRule = createLocalRegexRule("global", { + script_name: `通用规则 ${localRules.length + 1}`, + }); + draft.localRules = [...localRules, nextRule]; + return { selectRuleId: nextRule.id }; + }); + return; + case "delete-global-regex-rule": + _deleteGlobalRegexRule(actionEl.dataset.ruleId); + return; + case "select-global-regex-rule": + currentGlobalRegexRuleId = actionEl.dataset.ruleId || ""; + _refreshTaskProfileWorkspace(); + return; + case "restore-global-regex-defaults": { + const confirmed = window.confirm( + "这会将通用正则规则恢复为默认配置。是否继续?", + ); + if (!confirmed) return; + currentGlobalRegexRuleId = ""; + _patchGlobalTaskRegex(createDefaultGlobalTaskRegex(), { refresh: true }); + toastr.success("通用正则规则已恢复默认", "ST-BME"); + return; + } default: return; } @@ -5853,6 +6016,14 @@ function _renderTaskProfileWorkspace(state) { .join("")}
+ ${state.showGlobalRegex ? _renderGlobalRegexPanel(state) : ""} +