Merge pull request #95 from tomt610/feature/send-all-enabled-on-refresh

feat(history): Add 'Send All Enabled Stats on Refresh' option
This commit is contained in:
Spicy Marinara
2026-01-11 23:46:52 +01:00
committed by GitHub
3 changed files with 63 additions and 21 deletions
+2 -1
View File
@@ -55,7 +55,8 @@ export let extensionSettings = {
enabled: false, // Master toggle for history persistence feature enabled: false, // Master toggle for history persistence feature
messageCount: 5, // Number of messages to include (0 = all available) messageCount: 5, // Number of messages to include (0 = all available)
injectionPosition: 'assistant_message_end', // 'user_message_end', 'assistant_message_end', 'extra_user_message', 'extra_assistant_message' injectionPosition: 'assistant_message_end', // 'user_message_end', 'assistant_message_end', 'extra_user_message', 'extra_assistant_message'
contextPreamble: '' // Optional custom preamble text (empty = use default short one) contextPreamble: '', // Optional custom preamble text (empty = use default short one)
sendAllEnabledOnRefresh: false // If true, sends all enabled stats from preset instead of only persistInHistory-enabled stats on Refresh RPG Info
}, },
panelPosition: 'right', // 'left', 'right', or 'top' panelPosition: 'right', // 'left', 'right', or 'top'
theme: 'default', // Theme: default, sci-fi, fantasy, cyberpunk, custom theme: 'default', // Theme: default, sci-fi, fantasy, cyberpunk, custom
+40 -17
View File
@@ -740,19 +740,37 @@ function formatTrackerDataForContext(jsonData, trackerType, userName) {
/** /**
* Formats historical tracker data from a message's rpg_companion_swipes data. * Formats historical tracker data from a message's rpg_companion_swipes data.
* Only includes tracker fields that have persistInHistory enabled in trackerConfig. * Only includes tracker fields that have persistInHistory enabled in trackerConfig,
* unless useAllEnabled is true, in which case it includes all enabled fields.
* Uses the same formatting as formatTrackerDataForContext but filtered by persistence settings. * Uses the same formatting as formatTrackerDataForContext but filtered by persistence settings.
* *
* @param {Object} trackerData - The tracker data from message.extra.rpg_companion_swipes[swipeId] * @param {Object} trackerData - The tracker data from message.extra.rpg_companion_swipes[swipeId]
* @param {Object} trackerConfig - The tracker configuration from extensionSettings.trackerConfig * @param {Object} trackerConfig - The tracker configuration from extensionSettings.trackerConfig
* @param {string} userName - The user's name for personalization * @param {string} userName - The user's name for personalization
* @param {boolean} [useAllEnabled=false] - If true, include all enabled fields instead of only persistInHistory fields
* @returns {string} Formatted historical context or empty string if nothing to include * @returns {string} Formatted historical context or empty string if nothing to include
*/ */
export function formatHistoricalTrackerData(trackerData, trackerConfig, userName) { export function formatHistoricalTrackerData(trackerData, trackerConfig, userName, useAllEnabled = false) {
if (!trackerData || !trackerConfig) { if (!trackerData || !trackerConfig) {
return ''; return '';
} }
// Helper to check if a field should be included
const shouldInclude = (config) => {
if (useAllEnabled) {
return config?.enabled !== false; // Include if enabled (default true for most fields)
}
return config?.persistInHistory === true;
};
// Helper to check if a stat/attribute should be included
const shouldIncludeStat = (configStat) => {
if (useAllEnabled) {
return configStat?.enabled !== false;
}
return configStat?.persistInHistory === true;
};
let formatted = ''; let formatted = '';
// Helper to safely get values // Helper to safely get values
@@ -798,11 +816,11 @@ export function formatHistoricalTrackerData(trackerData, trackerConfig, userName
let statsFormatted = ''; let statsFormatted = '';
// Custom stats with persistInHistory enabled // Custom stats with persistInHistory enabled (or enabled if useAllEnabled)
if (userStatsData.stats && Array.isArray(userStatsData.stats) && userStatsConfig.customStats) { if (userStatsData.stats && Array.isArray(userStatsData.stats) && userStatsConfig.customStats) {
for (const stat of userStatsData.stats) { for (const stat of userStatsData.stats) {
const configStat = userStatsConfig.customStats.find(s => s.id === stat.id); const configStat = userStatsConfig.customStats.find(s => s.id === stat.id);
if (configStat?.persistInHistory && stat.value !== undefined) { if (shouldIncludeStat(configStat) && stat.value !== undefined) {
const statName = stat.name || configStat.name || stat.id; const statName = stat.name || configStat.name || stat.id;
statsFormatted += `${statName}: ${stat.value}, `; statsFormatted += `${statName}: ${stat.value}, `;
} }
@@ -810,7 +828,7 @@ export function formatHistoricalTrackerData(trackerData, trackerConfig, userName
} }
// Status section // Status section
if (userStatsConfig.statusSection?.persistInHistory && userStatsData.status) { if (shouldInclude(userStatsConfig.statusSection) && userStatsData.status) {
const mood = getValue(userStatsData.status.mood || userStatsData.status); const mood = getValue(userStatsData.status.mood || userStatsData.status);
const conditions = getValue(userStatsData.status.conditions); const conditions = getValue(userStatsData.status.conditions);
if (mood) statsFormatted += `Mood: ${mood}, `; if (mood) statsFormatted += `Mood: ${mood}, `;
@@ -818,7 +836,7 @@ export function formatHistoricalTrackerData(trackerData, trackerConfig, userName
} }
// Skills section // Skills section
if (userStatsConfig.skillsSection?.persistInHistory && userStatsData.skills) { if (shouldInclude(userStatsConfig.skillsSection) && userStatsData.skills) {
const skillsList = Array.isArray(userStatsData.skills) const skillsList = Array.isArray(userStatsData.skills)
? userStatsData.skills.map(s => getValue(s)).filter(s => s).join(', ') ? userStatsData.skills.map(s => getValue(s)).filter(s => s).join(', ')
: getValue(userStatsData.skills); : getValue(userStatsData.skills);
@@ -826,7 +844,8 @@ export function formatHistoricalTrackerData(trackerData, trackerConfig, userName
} }
// Inventory // Inventory
if (userStatsConfig.inventoryPersistInHistory && userStatsData.inventory) { const shouldIncludeInventory = useAllEnabled || userStatsConfig.inventoryPersistInHistory;
if (shouldIncludeInventory && userStatsData.inventory) {
const inv = userStatsData.inventory; const inv = userStatsData.inventory;
if (inv.onPerson && Array.isArray(inv.onPerson) && inv.onPerson.length > 0) { if (inv.onPerson && Array.isArray(inv.onPerson) && inv.onPerson.length > 0) {
const items = inv.onPerson.map(i => getValue(i)).filter(i => i); const items = inv.onPerson.map(i => getValue(i)).filter(i => i);
@@ -839,7 +858,8 @@ export function formatHistoricalTrackerData(trackerData, trackerConfig, userName
} }
// Quests // Quests
if (userStatsConfig.questsPersistInHistory && userStatsData.quests) { const shouldIncludeQuests = useAllEnabled || userStatsConfig.questsPersistInHistory;
if (shouldIncludeQuests && userStatsData.quests) {
const quests = userStatsData.quests; const quests = userStatsData.quests;
if (quests.main) { if (quests.main) {
const mainQuest = getValue(quests.main); const mainQuest = getValue(quests.main);
@@ -862,37 +882,37 @@ export function formatHistoricalTrackerData(trackerData, trackerConfig, userName
let infoFormatted = ''; let infoFormatted = '';
// Date // Date
if (infoBoxConfig.widgets.date?.persistInHistory && infoBoxData.date) { if (shouldInclude(infoBoxConfig.widgets.date) && infoBoxData.date) {
const date = getValue(infoBoxData.date); const date = getValue(infoBoxData.date);
if (date) infoFormatted += `Date: ${date}, `; if (date) infoFormatted += `Date: ${date}, `;
} }
// Time // Time
if (infoBoxConfig.widgets.time?.persistInHistory && infoBoxData.time) { if (shouldInclude(infoBoxConfig.widgets.time) && infoBoxData.time) {
const time = getValue(infoBoxData.time); const time = getValue(infoBoxData.time);
if (time) infoFormatted += `Time: ${time}, `; if (time) infoFormatted += `Time: ${time}, `;
} }
// Weather // Weather
if (infoBoxConfig.widgets.weather?.persistInHistory && infoBoxData.weather) { if (shouldInclude(infoBoxConfig.widgets.weather) && infoBoxData.weather) {
const weather = getValue(infoBoxData.weather); const weather = getValue(infoBoxData.weather);
if (weather) infoFormatted += `Weather: ${weather}, `; if (weather) infoFormatted += `Weather: ${weather}, `;
} }
// Temperature // Temperature
if (infoBoxConfig.widgets.temperature?.persistInHistory && infoBoxData.temperature) { if (shouldInclude(infoBoxConfig.widgets.temperature) && infoBoxData.temperature) {
const temp = getValue(infoBoxData.temperature); const temp = getValue(infoBoxData.temperature);
if (temp) infoFormatted += `Temp: ${temp}, `; if (temp) infoFormatted += `Temp: ${temp}, `;
} }
// Location // Location
if (infoBoxConfig.widgets.location?.persistInHistory && infoBoxData.location) { if (shouldInclude(infoBoxConfig.widgets.location) && infoBoxData.location) {
const location = getValue(infoBoxData.location); const location = getValue(infoBoxData.location);
if (location) infoFormatted += `Location: ${location}, `; if (location) infoFormatted += `Location: ${location}, `;
} }
// Recent Events // Recent Events
if (infoBoxConfig.widgets.recentEvents?.persistInHistory && infoBoxData.recentEvents) { if (shouldInclude(infoBoxConfig.widgets.recentEvents) && infoBoxData.recentEvents) {
const events = getValue(infoBoxData.recentEvents); const events = getValue(infoBoxData.recentEvents);
if (events) infoFormatted += `Events: ${events}, `; if (events) infoFormatted += `Events: ${events}, `;
} }
@@ -920,7 +940,7 @@ export function formatHistoricalTrackerData(trackerData, trackerConfig, userName
// Custom fields (appearance, demeanor, etc.) // Custom fields (appearance, demeanor, etc.)
if (char.details && typeof char.details === 'object') { if (char.details && typeof char.details === 'object') {
for (const field of charsConfig.customFields) { for (const field of charsConfig.customFields) {
if (field.persistInHistory && char.details[field.id]) { if (shouldIncludeStat(field) && char.details[field.id]) {
const value = getValue(char.details[field.id]); const value = getValue(char.details[field.id]);
if (value) charFormatted += `${field.name}: ${value}, `; if (value) charFormatted += `${field.name}: ${value}, `;
} }
@@ -928,7 +948,7 @@ export function formatHistoricalTrackerData(trackerData, trackerConfig, userName
} }
// Thoughts // Thoughts
if (charsConfig.thoughts?.persistInHistory && char.thoughts) { if (shouldInclude(charsConfig.thoughts) && char.thoughts) {
const thoughts = typeof char.thoughts === 'object' && char.thoughts.content const thoughts = typeof char.thoughts === 'object' && char.thoughts.content
? getValue(char.thoughts.content) ? getValue(char.thoughts.content)
: getValue(char.thoughts); : getValue(char.thoughts);
@@ -1208,7 +1228,10 @@ export async function generateSeparateUpdatePrompt() {
continue; continue;
} }
const formattedContext = formatHistoricalTrackerData(trackerData, trackerConfig, userName); // For Refresh RPG Info, use sendAllEnabledOnRefresh setting
// When true, include all enabled stats from preset instead of only persistInHistory stats
const useAllEnabled = historyPersistence.sendAllEnabledOnRefresh === true;
const formattedContext = formatHistoricalTrackerData(trackerData, trackerConfig, userName, useAllEnabled);
if (!formattedContext) { if (!formattedContext) {
continue; continue;
} }
+21 -3
View File
@@ -419,7 +419,8 @@ function resetToDefaults() {
enabled: false, enabled: false,
messageCount: 5, messageCount: 5,
injectionPosition: 'assistant_message_end', injectionPosition: 'assistant_message_end',
contextPreamble: '' contextPreamble: '',
sendAllEnabledOnRefresh: false
}; };
} }
@@ -1429,11 +1430,13 @@ function renderHistoryPersistenceTab() {
enabled: false, enabled: false,
messageCount: 5, messageCount: 5,
injectionPosition: 'assistant_message_end', injectionPosition: 'assistant_message_end',
contextPreamble: '' contextPreamble: '',
sendAllEnabledOnRefresh: false
}; };
const userStatsConfig = extensionSettings.trackerConfig.userStats; const userStatsConfig = extensionSettings.trackerConfig.userStats;
const infoBoxConfig = extensionSettings.trackerConfig.infoBox; const infoBoxConfig = extensionSettings.trackerConfig.infoBox;
const presentCharsConfig = extensionSettings.trackerConfig.presentCharacters; const presentCharsConfig = extensionSettings.trackerConfig.presentCharacters;
const generationMode = extensionSettings.generationMode || 'together';
let html = '<div class="rpg-editor-section">'; let html = '<div class="rpg-editor-section">';
@@ -1447,6 +1450,15 @@ function renderHistoryPersistenceTab() {
html += `<label for="rpg-history-persistence-enabled">Enable History Persistence</label>`; html += `<label for="rpg-history-persistence-enabled">Enable History Persistence</label>`;
html += '</div>'; html += '</div>';
// External API Only toggle - only show for separate/external modes
if (generationMode === 'separate' || generationMode === 'external') {
html += '<div class="rpg-editor-toggle-row" style="margin-top: 8px;">';
html += `<input type="checkbox" id="rpg-history-send-all-enabled" ${historyPersistence.sendAllEnabledOnRefresh ? 'checked' : ''}>`;
html += `<label for="rpg-history-send-all-enabled">Send All Enabled Stats on Refresh</label>`;
html += '</div>';
html += `<p class="rpg-editor-hint" style="margin-top: 4px; margin-left: 24px;">When enabled, Refresh RPG Info will include all enabled stats from the preset in history context, ignoring the individual selections below.</p>`;
}
// Message count // Message count
html += '<div class="rpg-editor-input-row" style="margin-top: 12px;">'; html += '<div class="rpg-editor-input-row" style="margin-top: 12px;">';
html += `<label for="rpg-history-message-count">Number of messages to include (0 = all available):</label>`; html += `<label for="rpg-history-message-count">Number of messages to include (0 = all available):</label>`;
@@ -1593,7 +1605,8 @@ function setupHistoryPersistenceListeners() {
enabled: false, enabled: false,
messageCount: 5, messageCount: 5,
injectionPosition: 'assistant_message_end', injectionPosition: 'assistant_message_end',
contextPreamble: '' contextPreamble: '',
externalApiOnly: false
}; };
} }
@@ -1602,6 +1615,11 @@ function setupHistoryPersistenceListeners() {
extensionSettings.historyPersistence.enabled = $(this).is(':checked'); extensionSettings.historyPersistence.enabled = $(this).is(':checked');
}); });
// Send All Enabled on Refresh toggle
$('#rpg-history-send-all-enabled').off('change').on('change', function() {
extensionSettings.historyPersistence.sendAllEnabledOnRefresh = $(this).is(':checked');
});
// Message count // Message count
$('#rpg-history-message-count').off('change').on('change', function() { $('#rpg-history-message-count').off('change').on('change', function() {
extensionSettings.historyPersistence.messageCount = parseInt($(this).val()) || 0; extensionSettings.historyPersistence.messageCount = parseInt($(this).val()) || 0;