Files
rpg-companion-sillytavern/src/systems/features/jsonCleaning.js
T

168 lines
6.7 KiB
JavaScript

/**
* JSON Cleaning Module
* Automatically registers a regex script to strip tracker JSON from Together mode output
*/
/**
* Registers an output transformation regex to remove tracker JSON from messages
* This uses SillyTavern's built-in regex system to transform text BEFORE display
* @param {Object} st_extension_settings - SillyTavern extension settings object
* @param {Function} saveSettingsDebounced - Function to save settings
*/
export async function ensureJsonCleaningRegex(st_extension_settings, saveSettingsDebounced) {
try {
// Validate extension settings structure
if (!st_extension_settings || typeof st_extension_settings !== 'object') {
console.warn('[RPG Companion] Invalid extension_settings object, skipping JSON cleaning regex');
return;
}
// Check if the JSON cleaning regex already exists
const scriptName = 'RPG Companion - Remove Tracker JSON (Together Mode)';
const existingScripts = st_extension_settings?.regex || [];
// Validate regex array
if (!Array.isArray(existingScripts)) {
console.warn('[RPG Companion] extension_settings.regex is not an array, resetting to empty array');
st_extension_settings.regex = [];
}
const existingScript = existingScripts.find(script =>
script && script.scriptName && script.scriptName === scriptName
);
if (existingScript) {
// Update existing script with new regex pattern if it's different
const newPattern = '/```(?:json|markdown)?[\\s\\S]*?```/gim';
// Always ensure these properties are set correctly
let needsSave = false;
if (existingScript.findRegex !== newPattern) {
existingScript.findRegex = newPattern;
needsSave = true;
}
if (JSON.stringify(existingScript.placement) !== JSON.stringify([2])) {
existingScript.placement = [2]; // 2 = AI Output
needsSave = true;
}
if (existingScript.disabled !== false) {
existingScript.disabled = false;
needsSave = true;
}
if (existingScript.runOnEdit !== true) {
existingScript.runOnEdit = true;
needsSave = true;
}
if (existingScript.markdownOnly !== true) {
existingScript.markdownOnly = true; // Only process markdown
needsSave = true;
}
if (existingScript.promptOnly !== true) {
existingScript.promptOnly = true; // Enable prompt processing
needsSave = true;
}
if (needsSave && typeof saveSettingsDebounced === 'function') {
// Force immediate save and wait for it
const saveResult = saveSettingsDebounced();
if (saveResult && typeof saveResult.then === 'function') {
await saveResult;
}
// Small delay to ensure save completes
await new Promise(resolve => setTimeout(resolve, 100));
console.log('[RPG Companion] ✅ Updated JSON cleaning regex to v3.2.3 settings.');
} else {
console.log('[RPG Companion] JSON Cleaning Regex is up to date.');
}
return;
}
// Generate a UUID for the script
const uuidv4 = () => {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
const r = Math.random() * 16 | 0;
const v = c === 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
};
// Create the regex script object for cleaning JSON tracker data
// This regex matches ```json...```, ```markdown...```, or plain ```...``` code blocks
// The prompt now explicitly instructs models to use this format
// Updated to handle various whitespace scenarios and ensure it catches all variations
const regexScript = {
id: uuidv4(),
scriptName: scriptName,
// Match ```json...```, ```markdown...```, or ```...``` code blocks (handles spaces, newlines, any content)
// Using a more permissive pattern to catch all variations
findRegex: '/```(?:json|markdown)?[\\s\\S]*?```/gim',
replaceString: '',
trimStrings: [],
placement: [2], // 2 = AI Output
disabled: false,
markdownOnly: true,
promptOnly: true, // Enable prompt processing
runOnEdit: true,
substituteRegex: 0,
minDepth: null,
maxDepth: null
};
// Add to global regex scripts
if (!Array.isArray(st_extension_settings.regex)) {
st_extension_settings.regex = [];
}
st_extension_settings.regex.push(regexScript);
console.log('[RPG Companion] JSON Cleaning Regex created and activated.');
// Save the changes
if (typeof saveSettingsDebounced === 'function') {
saveSettingsDebounced();
} else {
console.warn('[RPG Companion] saveSettingsDebounced is not a function, cannot save JSON cleaning regex');
}
} catch (error) {
console.error('[RPG Companion] JSON Cleaning Regex failed to properly initialize!');
console.error('[RPG Companion] Error details:', error.message, error.stack);
// Don't throw - continue without it
}
}
/**
* Removes the JSON cleaning regex if it exists
* Useful when switching to separate mode or disabling the feature
* @param {Object} st_extension_settings - SillyTavern extension settings object
* @param {Function} saveSettingsDebounced - Function to save settings
*/
export function removeJsonCleaningRegex(st_extension_settings, saveSettingsDebounced) {
try {
if (!st_extension_settings?.regex || !Array.isArray(st_extension_settings.regex)) {
return;
}
const scriptName = 'RPG Companion - Remove Tracker JSON (Together Mode)';
const initialLength = st_extension_settings.regex.length;
st_extension_settings.regex = st_extension_settings.regex.filter(script =>
!script || !script.scriptName || script.scriptName !== scriptName
);
if (st_extension_settings.regex.length < initialLength) {
// console.log('[RPG Companion] Removed JSON cleaning regex');
if (typeof saveSettingsDebounced === 'function') {
saveSettingsDebounced();
}
}
} catch (error) {
console.error('[RPG Companion] Failed to remove JSON cleaning regex:', error);
}
}