feat(history): Add 'Send All Enabled Stats on Refresh' option
Adds a new toggle in Edit Trackers -> History Persistence that allows sending all enabled stats from the preset when using Refresh RPG Info, instead of only the individually selected persistInHistory fields. This helps the separate update AI understand the full context of what has already been tracked and what changes it needs to account for, improving coherence in stat updates without cluttering the main chat history with excessive context data.
This commit is contained in:
+2
-1
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user