fix: add debug logging and fix Present Characters rendering
PROBLEM (reported by Salixfire):
- Present Characters panel showing placeholder instead of actual characters
- Thought bubbles work correctly but main panel doesn't
- Need to toggle settings off/on to get thoughts to appear
- No way to debug on mobile devices
CHANGES:
1. Added comprehensive debug logging to renderThoughts() (src/systems/rendering/thoughts.js):
- Log when function is called and with what data
- Log each line being parsed and how many parts it has
- Log character extraction (emoji, name, traits, relationship, thoughts)
- Log why characters are accepted or rejected
- Log final character count and whether showing placeholder
- All logs visible in mobile-friendly debug panel
2. Fixed toggle to refresh content (index.js:283-291):
- When user toggles "Show Present Characters" on, now calls renderThoughts()
- Previously only showed/hid container without refreshing content
- This ensures panel displays latest data when toggled
3. Normalized parsing logic (src/systems/rendering/thoughts.js:111):
- Changed renderThoughts() to require >= 3 parts (was >= 2)
- Now matches updateChatThoughts() requirement
- Consistent with current prompt format: Emoji:Name | Relationship | Thoughts
- Removed 2-part format fallback code (unreachable now)
- Both functions now use same validation rules
EXPECTED OUTCOME:
- User can enable debug mode and see exactly what data is being parsed
- Toggle will properly refresh the panel content
- We can diagnose from debug logs why placeholder is shown
- More consistent behavior between main panel and thought bubbles
Debug logs will help us identify:
- If characterThoughts data is empty/malformed when renderThoughts() is called
- If parsing is rejecting valid character data
- If there's a timing issue with data availability
- What the actual AI response format looks like
Related to previous commit (37878fc) that added debug mode toggle.
This commit is contained in:
@@ -284,6 +284,10 @@ async function initUI() {
|
|||||||
extensionSettings.showCharacterThoughts = $(this).prop('checked');
|
extensionSettings.showCharacterThoughts = $(this).prop('checked');
|
||||||
saveSettings();
|
saveSettings();
|
||||||
updateSectionVisibility();
|
updateSectionVisibility();
|
||||||
|
// Refresh the content when toggling on/off
|
||||||
|
if (extensionSettings.showCharacterThoughts) {
|
||||||
|
renderThoughts();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#rpg-toggle-inventory').on('change', function() {
|
$('#rpg-toggle-inventory').on('change', function() {
|
||||||
|
|||||||
@@ -11,11 +11,22 @@ import {
|
|||||||
lastGeneratedData,
|
lastGeneratedData,
|
||||||
committedTrackerData,
|
committedTrackerData,
|
||||||
$thoughtsContainer,
|
$thoughtsContainer,
|
||||||
FALLBACK_AVATAR_DATA_URI
|
FALLBACK_AVATAR_DATA_URI,
|
||||||
|
addDebugLog
|
||||||
} from '../../core/state.js';
|
} from '../../core/state.js';
|
||||||
import { saveChatData } from '../../core/persistence.js';
|
import { saveChatData } from '../../core/persistence.js';
|
||||||
import { getSafeThumbnailUrl } from '../../utils/avatars.js';
|
import { getSafeThumbnailUrl } from '../../utils/avatars.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper to log to both console and debug logs array
|
||||||
|
*/
|
||||||
|
function debugLog(message, data = null) {
|
||||||
|
console.log(message, data || '');
|
||||||
|
if (extensionSettings.debugMode) {
|
||||||
|
addDebugLog(message, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fuzzy name matching that handles:
|
* Fuzzy name matching that handles:
|
||||||
* - Exact matches: "Sabrina" === "Sabrina"
|
* - Exact matches: "Sabrina" === "Sabrina"
|
||||||
@@ -54,6 +65,10 @@ export function renderThoughts() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
debugLog('[RPG Thoughts] ==================== RENDERING PRESENT CHARACTERS ====================');
|
||||||
|
debugLog('[RPG Thoughts] showCharacterThoughts setting:', extensionSettings.showCharacterThoughts);
|
||||||
|
debugLog('[RPG Thoughts] Container exists:', !!$thoughtsContainer);
|
||||||
|
|
||||||
// Add updating class for animation
|
// Add updating class for animation
|
||||||
if (extensionSettings.enableAnimations) {
|
if (extensionSettings.enableAnimations) {
|
||||||
$thoughtsContainer.addClass('rpg-content-updating');
|
$thoughtsContainer.addClass('rpg-content-updating');
|
||||||
@@ -64,25 +79,36 @@ export function renderThoughts() {
|
|||||||
lastGeneratedData.characterThoughts = '';
|
lastGeneratedData.characterThoughts = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
debugLog('[RPG Thoughts] Raw characterThoughts data:', lastGeneratedData.characterThoughts);
|
||||||
|
debugLog('[RPG Thoughts] Data length:', lastGeneratedData.characterThoughts.length + ' chars');
|
||||||
|
|
||||||
const lines = lastGeneratedData.characterThoughts.split('\n');
|
const lines = lastGeneratedData.characterThoughts.split('\n');
|
||||||
const presentCharacters = [];
|
const presentCharacters = [];
|
||||||
|
|
||||||
// console.log('[RPG Companion] Raw Present Characters:', lastGeneratedData.characterThoughts);
|
debugLog('[RPG Thoughts] Split into lines count:', lines.length);
|
||||||
// console.log('[RPG Companion] Split into lines:', lines);
|
debugLog('[RPG Thoughts] Lines:', lines);
|
||||||
|
|
||||||
// Parse format: [Emoji]: [Name, Status, Demeanor] | [Relationship] | [Thoughts]
|
// Parse format: [Emoji]: [Name, Status, Demeanor] | [Relationship] | [Thoughts]
|
||||||
// Also supports 4-part format: [Emoji]: [Name, Status] | [Demeanor] | [Relationship] | [Thoughts]
|
// Also supports 4-part format: [Emoji]: [Name, Status] | [Demeanor] | [Relationship] | [Thoughts]
|
||||||
|
let lineNumber = 0;
|
||||||
for (const line of lines) {
|
for (const line of lines) {
|
||||||
|
lineNumber++;
|
||||||
|
|
||||||
// Skip empty lines, headers, dividers, and code fences
|
// Skip empty lines, headers, dividers, and code fences
|
||||||
if (line.trim() &&
|
if (line.trim() &&
|
||||||
!line.includes('Present Characters') &&
|
!line.includes('Present Characters') &&
|
||||||
!line.includes('---') &&
|
!line.includes('---') &&
|
||||||
!line.trim().startsWith('```')) {
|
!line.trim().startsWith('```')) {
|
||||||
|
|
||||||
|
debugLog(`[RPG Thoughts] Processing line ${lineNumber}:`, line);
|
||||||
|
|
||||||
// Match the new format with pipes
|
// Match the new format with pipes
|
||||||
const parts = line.split('|').map(p => p.trim());
|
const parts = line.split('|').map(p => p.trim());
|
||||||
|
debugLog(`[RPG Thoughts] Split into ${parts.length} parts:`, parts);
|
||||||
|
|
||||||
if (parts.length >= 2) {
|
// Require at least 3 parts (Emoji:Name | Relationship | Thoughts)
|
||||||
|
// This matches updateChatThoughts() and the current prompt format
|
||||||
|
if (parts.length >= 3) {
|
||||||
// First part: [Emoji]: [Name, Status, Demeanor]
|
// First part: [Emoji]: [Name, Status, Demeanor]
|
||||||
const firstPart = parts[0].trim();
|
const firstPart = parts[0].trim();
|
||||||
const emojiMatch = firstPart.match(/^(.+?):\s*(.+)$/);
|
const emojiMatch = firstPart.match(/^(.+?):\s*(.+)$/);
|
||||||
@@ -91,6 +117,8 @@ export function renderThoughts() {
|
|||||||
const emoji = emojiMatch[1].trim();
|
const emoji = emojiMatch[1].trim();
|
||||||
const info = emojiMatch[2].trim();
|
const info = emojiMatch[2].trim();
|
||||||
|
|
||||||
|
debugLog(`[RPG Thoughts] Emoji match found - emoji: "${emoji}", info: "${info}"`);
|
||||||
|
|
||||||
// Handle both 3-part and 4-part formats
|
// Handle both 3-part and 4-part formats
|
||||||
let relationship, thoughts, traits;
|
let relationship, thoughts, traits;
|
||||||
|
|
||||||
@@ -100,7 +128,8 @@ export function renderThoughts() {
|
|||||||
thoughts = parts[2].trim();
|
thoughts = parts[2].trim();
|
||||||
const infoParts = info.split(',').map(p => p.trim());
|
const infoParts = info.split(',').map(p => p.trim());
|
||||||
traits = infoParts.slice(1).join(', ');
|
traits = infoParts.slice(1).join(', ');
|
||||||
} else if (parts.length >= 4) {
|
debugLog('[RPG Thoughts] Parsed as 3-part format');
|
||||||
|
} else {
|
||||||
// 4-part format: Emoji:Name,traits | Demeanor | Relationship | Thoughts
|
// 4-part format: Emoji:Name,traits | Demeanor | Relationship | Thoughts
|
||||||
// Add the demeanor to traits and use last two parts for relationship/thoughts
|
// Add the demeanor to traits and use last two parts for relationship/thoughts
|
||||||
const demeanor = parts[1].trim();
|
const demeanor = parts[1].trim();
|
||||||
@@ -109,23 +138,26 @@ export function renderThoughts() {
|
|||||||
const infoParts = info.split(',').map(p => p.trim());
|
const infoParts = info.split(',').map(p => p.trim());
|
||||||
const baseTraits = infoParts.slice(1).join(', ');
|
const baseTraits = infoParts.slice(1).join(', ');
|
||||||
traits = baseTraits ? `${baseTraits}, ${demeanor}` : demeanor;
|
traits = baseTraits ? `${baseTraits}, ${demeanor}` : demeanor;
|
||||||
} else {
|
debugLog('[RPG Thoughts] Parsed as 4-part format');
|
||||||
// Fallback for 2-part format
|
|
||||||
relationship = parts[1].trim();
|
|
||||||
thoughts = '';
|
|
||||||
const infoParts = info.split(',').map(p => p.trim());
|
|
||||||
traits = infoParts.slice(1).join(', ');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse name from info (first part before comma)
|
// Parse name from info (first part before comma)
|
||||||
const infoParts = info.split(',').map(p => p.trim());
|
const infoParts = info.split(',').map(p => p.trim());
|
||||||
const name = infoParts[0] || '';
|
const name = infoParts[0] || '';
|
||||||
|
|
||||||
|
debugLog(`[RPG Thoughts] Extracted - name: "${name}", traits: "${traits}", relationship: "${relationship}", thoughts: "${thoughts}"`);
|
||||||
|
|
||||||
if (name && name.toLowerCase() !== 'unavailable') {
|
if (name && name.toLowerCase() !== 'unavailable') {
|
||||||
presentCharacters.push({ emoji, name, traits, relationship, thoughts });
|
presentCharacters.push({ emoji, name, traits, relationship, thoughts });
|
||||||
// console.log('[RPG Companion] Parsed character:', { name, relationship, thoughts });
|
debugLog(`[RPG Thoughts] ✓ Added character: ${name}`);
|
||||||
|
} else {
|
||||||
|
debugLog(`[RPG Thoughts] ✗ Rejected character - name: "${name}" (unavailable or empty)`);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
debugLog('[RPG Thoughts] ✗ No emoji match found in first part');
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
debugLog(`[RPG Thoughts] ✗ Not enough parts (${parts.length} < 3, need at least Emoji:Name | Relationship | Thoughts)`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -138,14 +170,16 @@ export function renderThoughts() {
|
|||||||
'Lover': '❤️'
|
'Lover': '❤️'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
debugLog('[RPG Thoughts] ==================== PARSING COMPLETE ====================');
|
||||||
|
debugLog('[RPG Thoughts] Total characters parsed:', presentCharacters.length);
|
||||||
|
debugLog('[RPG Thoughts] Characters array:', presentCharacters);
|
||||||
|
|
||||||
// Build HTML
|
// Build HTML
|
||||||
let html = '';
|
let html = '';
|
||||||
|
|
||||||
// console.log('[RPG Companion] Total characters parsed:', presentCharacters.length);
|
|
||||||
// console.log('[RPG Companion] Characters array:', presentCharacters);
|
|
||||||
|
|
||||||
// If no characters parsed, show a placeholder editable card
|
// If no characters parsed, show a placeholder editable card
|
||||||
if (presentCharacters.length === 0) {
|
if (presentCharacters.length === 0) {
|
||||||
|
debugLog('[RPG Thoughts] ⚠ No characters parsed - showing placeholder card');
|
||||||
// Get default character portrait (try to use the current character if in 1-on-1 chat)
|
// Get default character portrait (try to use the current character if in 1-on-1 chat)
|
||||||
// Use a base64-encoded SVG placeholder as fallback to avoid 400 errors
|
// Use a base64-encoded SVG placeholder as fallback to avoid 400 errors
|
||||||
let defaultPortrait = FALLBACK_AVATAR_DATA_URI;
|
let defaultPortrait = FALLBACK_AVATAR_DATA_URI;
|
||||||
@@ -249,6 +283,9 @@ export function renderThoughts() {
|
|||||||
|
|
||||||
$thoughtsContainer.html(html);
|
$thoughtsContainer.html(html);
|
||||||
|
|
||||||
|
debugLog('[RPG Thoughts] ✓ HTML rendered to container');
|
||||||
|
debugLog('[RPG Thoughts] =======================================================');
|
||||||
|
|
||||||
// Add event handlers for editable character fields
|
// Add event handlers for editable character fields
|
||||||
$thoughtsContainer.find('.rpg-editable').on('blur', function() {
|
$thoughtsContainer.find('.rpg-editable').on('blur', function() {
|
||||||
const character = $(this).data('character');
|
const character = $(this).data('character');
|
||||||
|
|||||||
Reference in New Issue
Block a user