diff --git a/README.md b/README.md index d427e91..dc7d13a 100644 --- a/README.md +++ b/README.md @@ -7,34 +7,20 @@ An immersive RPG extension for browsers that tracks character stats, scene infor ## ๐Ÿ†• What's New +### v3.1.0 + +- Added toastr notification when the model returns an incorrect tracker format that cannot be parsed. +- Added guidance in settings about which models work best with the extension (I'm tired of people asking me why this doesn't work with their Q4 MythoMax 13B). +- Fixed auto-update after messages to work with External API generation mode. +- Fixed mobile UI. +- Fixed a minor bug with the thought bubble icon appearing in the wrong place on mobiles. + ### v3.0.1 - Small bug fix where you couldn't edit the thought bubble. -### v3.0.0 - -**What's new?** -- Switched to the JSON format for the trackers. -- You can now lock/unlock trackers that you don't want the model to change between generations. -- Removed features that were half-baked or didn't work. -- Organized Settings and Edit Trackers windows. -- All features of the extension are now accessible from the main panel view. -- Added Colored Dialogues option that makes the model color dialogue lines differently depending on the speaker. -- Introduced Dynamic Weather Effects that add visual effects to your SillyTavern window depending on the current weather from the trackers. -- All prompts used for the extension's features are now editable. -- Made the user's level optional in the Edit Trackers. - -**Bug Fixes:** -- Fixed tracker logic in Together generation mode. -- Fixed various UI bugs (too many to count). -- Upgraded mobile view. -- Spotify Music widget is more visible now, plus it works in the mobile view. -- Auto-update after messages option is now available for External API generation mode. -- Fixed the display of the thoughts window and its mobile display. -- Fixed smaller bugs. - **Special thanks to all the other contributors for this project:** -Paperboygold, Munimunigamer, Subarashimo, Lilminzyu, Claude, IDeathByte, Chungchandev, Joenunezb, and Amauragis! +Paperboygold, Munimunigamer, Subarashimo, Lilminzyu, Claude, IDeathByte, Chungchandev, Joenunezb, and Amauragis. ## ๐Ÿ“ฅ Installation @@ -287,7 +273,7 @@ If you enjoy this extension, consider supporting development: ## ๐Ÿ™ Credits **Contributors:** -SpicyMarinara, Paperboygold, Munimunigamer, Subarashimo, Lilminzyu, Claude, IDeathByte, Chungchandev, Joenunezb, and Amauragis +SpicyMarinara, Paperboygold, Munimunigamer, Subarashimo, Lilminzyu, Claude, IDeathByte, Chungchandev, Joenunezb, and Amauragis. ## ๐Ÿš€ Planned Features diff --git a/index.js b/index.js index bd71a7a..01b2ec9 100644 --- a/index.js +++ b/index.js @@ -253,7 +253,7 @@ async function initUI() { // Only initialize UI if extension is enabled if (!extensionSettings.enabled) { - console.log('[RPG Companion] Extension disabled - skipping UI initialization'); + // console.log('[RPG Companion] Extension disabled - skipping UI initialization'); return; } @@ -941,11 +941,11 @@ jQuery(async () => { // Check if migration to v3 JSON format is needed try { if (extensionSettings.settingsVersion < 3) { - console.log('[RPG Companion] Detected v2 format, migrating to v3 JSON...'); + // console.log('[RPG Companion] Detected v2 format, migrating to v3 JSON...'); await migrateToV3JSON(); updateExtensionSettings({ settingsVersion: 3 }); await saveSettings(); - console.log('[RPG Companion] โœ… Migration to v3 complete'); + // console.log('[RPG Companion] โœ… Migration to v3 complete'); } } catch (error) { console.error('[RPG Companion] Migration to v3 failed:', error); @@ -1014,9 +1014,9 @@ jQuery(async () => { try { const conflicts = detectConflictingRegexScripts(st_extension_settings); if (conflicts.length > 0) { - console.log('[RPG Companion] โš ๏ธ Detected old manual formatting regex scripts that may conflict:'); - conflicts.forEach(name => console.log(` - ${name}`)); - console.log('[RPG Companion] Consider disabling these regexes as the extension now handles formatting automatically.'); + // console.log('[RPG Companion] โš ๏ธ Detected old manual formatting regex scripts that may conflict:'); + // conflicts.forEach(name => console.log(` - ${name}`)); + // console.log('[RPG Companion] Consider disabling these regexes as the extension now handles formatting automatically.'); // Show user-friendly warning (non-blocking) // toastr.warning( @@ -1067,7 +1067,7 @@ jQuery(async () => { // Non-critical - continue without it } - console.log('[RPG Companion] โœ… Extension loaded successfully'); + // console.log('[RPG Companion] โœ… Extension loaded successfully'); } catch (error) { console.error('[RPG Companion] โŒ Critical initialization failure:', error); console.error('[RPG Companion] Error details:', error.message, error.stack); diff --git a/manifest.json b/manifest.json index fc1b264..9d238a3 100644 --- a/manifest.json +++ b/manifest.json @@ -6,6 +6,6 @@ "js": "index.js", "css": "style.css", "author": "Marinara", - "version": "3.0.1", + "version": "3.1.0", "homePage": "https://github.com/SpicyMarinara/rpg-companion-sillytavern" } diff --git a/settings.html b/settings.html index 9564b89..c2c7993 100644 --- a/settings.html +++ b/settings.html @@ -29,17 +29,26 @@ +
+
+ Recommended Models: +
+
+ For the extension to work properly, it is not recommended to use any models below 20B, especially if they're old. It works best with the SOTA models such as Deepseek, Claude, GPT, or Gemini. +
+
+
Contributors:
- SpicyMarinara, Paperboygold, Munimunigamer, Subarashimo, Lilminzyu, Claude, IDeathByte, Chungchandev, Joenunezb, and Amauragis + SpicyMarinara, Paperboygold, Munimunigamer, Subarashimo, Lilminzyu, Claude, IDeathByte, Chungchandev, Joenunezb, and Amauragis.
- v3.0.1 + v3.1.0
diff --git a/src/core/persistence.js b/src/core/persistence.js index 5297f12..a495e26 100644 --- a/src/core/persistence.js +++ b/src/core/persistence.js @@ -86,7 +86,7 @@ export function loadSettings() { // Migration to version 2: Enable dynamic weather for existing users if (currentVersion < 2) { - console.log('[RPG Companion] Migrating settings to version 2 (enabling dynamic weather)'); + // console.log('[RPG Companion] Migrating settings to version 2 (enabling dynamic weather)'); extensionSettings.enableDynamicWeather = true; extensionSettings.settingsVersion = 2; settingsChanged = true; @@ -94,7 +94,7 @@ export function loadSettings() { // Migration to version 3: Convert text trackers to JSON format if (currentVersion < 3) { - console.log('[RPG Companion] Migrating settings to version 3 (JSON tracker format)'); + // console.log('[RPG Companion] Migrating settings to version 3 (JSON tracker format)'); migrateToV3JSON(); extensionSettings.settingsVersion = 3; settingsChanged = true; @@ -114,7 +114,7 @@ export function loadSettings() { if (FEATURE_FLAGS.useNewInventory) { const migrationResult = migrateInventory(extensionSettings.userStats.inventory); if (migrationResult.migrated) { - console.log(`[RPG Companion] Inventory migrated from ${migrationResult.source} to v2 format`); + // console.log(`[RPG Companion] Inventory migrated from ${migrationResult.source} to v2 format`); extensionSettings.userStats.inventory = migrationResult.inventory; saveSettings(); // Persist migrated inventory } @@ -122,7 +122,7 @@ export function loadSettings() { // Migrate to trackerConfig if it doesn't exist if (!extensionSettings.trackerConfig) { - console.log('[RPG Companion] Migrating to trackerConfig format'); + // console.log('[RPG Companion] Migrating to trackerConfig format'); migrateToTrackerConfig(); saveSettings(); // Persist migration } @@ -161,13 +161,13 @@ export function saveChatData() { return; } - console.log('[RPG Companion] ๐Ÿ’พ saveChatData called - committedTrackerData:', { - userStats: committedTrackerData.userStats ? `${committedTrackerData.userStats.substring(0, 50)}...` : 'null', - infoBox: committedTrackerData.infoBox ? 'exists' : 'null', - characterThoughts: committedTrackerData.characterThoughts ? 'exists' : 'null' - }); - console.log('[RPG Companion] ๐Ÿ’พ saveChatData RAW committedTrackerData:', committedTrackerData); - console.log('[RPG Companion] ๐Ÿ’พ saveChatData RAW lastGeneratedData:', lastGeneratedData); + // console.log('[RPG Companion] ๐Ÿ’พ saveChatData called - committedTrackerData:', { + // userStats: committedTrackerData.userStats ? `${committedTrackerData.userStats.substring(0, 50)}...` : 'null', + // infoBox: committedTrackerData.infoBox ? 'exists' : 'null', + // characterThoughts: committedTrackerData.characterThoughts ? 'exists' : 'null' + // }); + // console.log('[RPG Companion] ๐Ÿ’พ saveChatData RAW committedTrackerData:', committedTrackerData); + // console.log('[RPG Companion] ๐Ÿ’พ saveChatData RAW lastGeneratedData:', lastGeneratedData); chat_metadata.rpg_companion = { userStats: extensionSettings.userStats, @@ -284,34 +284,34 @@ export function loadChatData() { // Restore committed tracker data first if (savedData.committedTrackerData) { - console.log('[RPG Companion] ๐Ÿ“ฅ loadChatData restoring committedTrackerData:', { - userStats: savedData.committedTrackerData.userStats ? `${savedData.committedTrackerData.userStats.substring(0, 50)}...` : 'null', - infoBox: savedData.committedTrackerData.infoBox ? 'exists' : 'null', - characterThoughts: savedData.committedTrackerData.characterThoughts ? 'exists' : 'null' - }); - console.log('[RPG Companion] ๐Ÿ“ฅ RAW savedData.committedTrackerData:', savedData.committedTrackerData); - console.log('[RPG Companion] ๐Ÿ“ฅ Type check:', { - userStatsType: typeof savedData.committedTrackerData.userStats, - infoBoxType: typeof savedData.committedTrackerData.infoBox, - characterThoughtsType: typeof savedData.committedTrackerData.characterThoughts - }); + // console.log('[RPG Companion] ๐Ÿ“ฅ loadChatData restoring committedTrackerData:', { + // userStats: savedData.committedTrackerData.userStats ? `${savedData.committedTrackerData.userStats.substring(0, 50)}...` : 'null', + // infoBox: savedData.committedTrackerData.infoBox ? 'exists' : 'null', + // characterThoughts: savedData.committedTrackerData.characterThoughts ? 'exists' : 'null' + // }); + // console.log('[RPG Companion] ๐Ÿ“ฅ RAW savedData.committedTrackerData:', savedData.committedTrackerData); + // console.log('[RPG Companion] ๐Ÿ“ฅ Type check:', { + // userStatsType: typeof savedData.committedTrackerData.userStats, + // infoBoxType: typeof savedData.committedTrackerData.infoBox, + // characterThoughtsType: typeof savedData.committedTrackerData.characterThoughts + // }); setCommittedTrackerData({ ...savedData.committedTrackerData }); } // Restore last generated data (for display) // Always prefer lastGeneratedData as it contains the most recent generation (including swipes) if (savedData.lastGeneratedData) { - console.log('[RPG Companion] ๐Ÿ“ฅ loadChatData restoring lastGeneratedData'); + // console.log('[RPG Companion] ๐Ÿ“ฅ loadChatData restoring lastGeneratedData'); setLastGeneratedData({ ...savedData.lastGeneratedData }); } else { - console.log('[RPG Companion] โš ๏ธ No lastGeneratedData found in save'); + // console.log('[RPG Companion] โš ๏ธ No lastGeneratedData found in save'); } // Migrate inventory in chat data if feature flag enabled if (FEATURE_FLAGS.useNewInventory && extensionSettings.userStats.inventory) { const migrationResult = migrateInventory(extensionSettings.userStats.inventory); if (migrationResult.migrated) { - console.log(`[RPG Companion] Chat inventory migrated from ${migrationResult.source} to v2 format`); + // console.log(`[RPG Companion] Chat inventory migrated from ${migrationResult.source} to v2 format`); extensionSettings.userStats.inventory = migrationResult.inventory; saveChatData(); // Persist migrated inventory to chat metadata } @@ -401,7 +401,7 @@ function validateInventoryStructure(inventory, source) { // Persist repairs if needed if (needsSave) { - console.log(`[RPG Companion] Repaired inventory structure from ${source}, saving...`); + // console.log(`[RPG Companion] Repaired inventory structure from ${source}, saving...`); saveSettings(); if (source === 'chat') { saveChatData(); @@ -473,7 +473,7 @@ function migrateToTrackerConfig() { name: extensionSettings.statNames[id] || id.charAt(0).toUpperCase() + id.slice(1), enabled: true })); - console.log('[RPG Companion] Migrated statNames to customStats array'); + // console.log('[RPG Companion] Migrated statNames to customStats array'); } // Ensure all stats have corresponding values in userStats @@ -497,7 +497,7 @@ function migrateToTrackerConfig() { { id: 'cha', name: 'CHA', enabled: shouldShow } ]; delete extensionSettings.trackerConfig.userStats.showRPGAttributes; - console.log('[RPG Companion] Migrated showRPGAttributes to rpgAttributes array'); + // console.log('[RPG Companion] Migrated showRPGAttributes to rpgAttributes array'); } // Ensure rpgAttributes exists even if no migration was needed @@ -535,7 +535,7 @@ function migrateToTrackerConfig() { const hasOldFormat = pc.customFields.some(f => f.label || f.placeholder || f.type === 'relationship'); if (hasOldFormat) { - console.log('[RPG Companion] Migrating Present Characters to new structure'); + // console.log('[RPG Companion] Migrating Present Characters to new structure'); // Extract relationship fields from old customFields const relationshipFields = ['Lover', 'Friend', 'Ally', 'Enemy', 'Neutral']; @@ -563,7 +563,7 @@ function migrateToTrackerConfig() { pc.customFields = newCustomFields; pc.thoughts = thoughts; - console.log('[RPG Companion] Present Characters migration complete'); + // console.log('[RPG Companion] Present Characters migration complete'); saveSettings(); // Persist the migration } } diff --git a/src/core/state.js b/src/core/state.js index ecf07a7..97647fd 100644 --- a/src/core/state.js +++ b/src/core/state.js @@ -376,24 +376,24 @@ export function updateLastGeneratedData(updates) { } export function setCommittedTrackerData(data) { - console.log('[RPG State] setCommittedTrackerData called with:', data); - console.log('[RPG State] Type check on input:', { - userStatsType: typeof data.userStats, - infoBoxType: typeof data.infoBox, - characterThoughtsType: typeof data.characterThoughts, - userStatsValue: data.userStats, - infoBoxValue: data.infoBox, - characterThoughtsValue: data.characterThoughts - }); + // console.log('[RPG State] setCommittedTrackerData called with:', data); + // console.log('[RPG State] Type check on input:', { + // userStatsType: typeof data.userStats, + // infoBoxType: typeof data.infoBox, + // characterThoughtsType: typeof data.characterThoughts, + // userStatsValue: data.userStats, + // infoBoxValue: data.infoBox, + // characterThoughtsValue: data.characterThoughts + // }); committedTrackerData = data; - console.log('[RPG State] committedTrackerData after assignment:', committedTrackerData); + // console.log('[RPG State] committedTrackerData after assignment:', committedTrackerData); } export function updateCommittedTrackerData(updates) { - console.log('[RPG State] updateCommittedTrackerData called with:', updates); - console.log('[RPG State] committedTrackerData before update:', committedTrackerData); + // console.log('[RPG State] updateCommittedTrackerData called with:', updates); + // console.log('[RPG State] committedTrackerData before update:', committedTrackerData); Object.assign(committedTrackerData, updates); - console.log('[RPG State] committedTrackerData after update:', committedTrackerData); + // console.log('[RPG State] committedTrackerData after update:', committedTrackerData); } export function setLastActionWasSwipe(value) { diff --git a/src/i18n/en.json b/src/i18n/en.json index 4e337f5..270fe8e 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -230,5 +230,8 @@ "checkpoint.indicator": "Chapter Start", "checkpoint.tooltip": "Messages before this point are excluded from context", "musicPlayer.title": "Scene Music", - "musicPlayer.noMusic": "AI will suggest music when appropriate for the scene" + "musicPlayer.noMusic": "AI will suggest music when appropriate for the scene", + "errors.parsingError": "RPG Companion Trackers' parsing error! The model returned an incorrect format. If the issue persists, consider changing the model for generations.", + "settings.recommendedModels.title": "Recommended Models", + "settings.recommendedModels.description": "For the extension to work properly, **it is not recommended to use any models below 20B, especially if they're old.** It works best with the SOTA models such as Deepseek, Claude, GPT, or Gemini." } diff --git a/src/i18n/zh-tw.json b/src/i18n/zh-tw.json index 1e55e56..51b5e79 100644 --- a/src/i18n/zh-tw.json +++ b/src/i18n/zh-tw.json @@ -193,5 +193,8 @@ "quests.optional.empty": "็•ถๅ‰็„กๆ”ฏ็ทšไปปๅ‹™ (ส˜ฬ†สšส˜ฬ†)", "quests.optional.hint": "ๆ”ฏ็ทšไปปๅ‹™ๆ˜ฏ่ฃœๅ……ไธป็ทšๅЇๆƒ…็š„ๆ”ฏ็ทš็›ฎๆจ™ใ€‚", "musicPlayer.title": "ๅ ดๆ™ฏ้Ÿณๆจ‚", - "musicPlayer.noMusic": "AI ๆœƒๅœจ้ฉ็•ถๆ™‚็‚บๅ ดๆ™ฏๅปบ่ญฐ้Ÿณๆจ‚" + "musicPlayer.noMusic": "AI ๆœƒๅœจ้ฉ็•ถๆ™‚็‚บๅ ดๆ™ฏๅปบ่ญฐ้Ÿณๆจ‚", + "errors.parsingError": "RPG Companion ่ฟฝ่นคๅ™จ่งฃๆž้Œฏ่ชค๏ผๆจกๅž‹่ฟ”ๅ›žไบ†ไธๆญฃ็ขบ็š„ๆ ผๅผใ€‚ๅฆ‚ๆžœๅ•้กŒๆŒ็บŒๅญ˜ๅœจ๏ผŒ่ซ‹่€ƒๆ…ฎๆ›ดๆ›็”Ÿๆˆๆจกๅž‹ใ€‚", + "settings.recommendedModels.title": "ๆŽจ่–ฆๆจกๅž‹", + "settings.recommendedModels.description": "็‚บไบ†่ฎ“ๆ“ดๅ……ๅŠŸ่ƒฝๆญฃๅธธ้‹ไฝœ๏ผŒ**ไธๅปบ่ญฐไฝฟ็”จไปปไฝ•ๅฐๆ–ผ 20B ็š„ๆจกๅž‹๏ผŒๅฐคๅ…ถๆ˜ฏ่ˆŠๆจกๅž‹ใ€‚**ๅฎƒๆœ€้ฉๅˆไฝฟ็”จ SOTA ๆจกๅž‹๏ผŒไพ‹ๅฆ‚ Deepseekใ€Claudeใ€GPT ๆˆ– Geminiใ€‚" } diff --git a/src/systems/features/avatarGenerator.js b/src/systems/features/avatarGenerator.js index df60c8d..629bb41 100644 --- a/src/systems/features/avatarGenerator.js +++ b/src/systems/features/avatarGenerator.js @@ -147,7 +147,7 @@ export async function generateAvatarsForCharacters(characterNames, onStarted = n return; } - console.log('[RPG Avatar] Starting batch generation for:', needsGeneration); + // console.log('[RPG Avatar] Starting batch generation for:', needsGeneration); // Mark all as pending IMMEDIATELY (before any async work) for (const name of needsGeneration) { @@ -192,7 +192,7 @@ export async function generateAvatarsForCharacters(characterNames, onStarted = n } } - console.log('[RPG Avatar] Batch generation complete'); + // console.log('[RPG Avatar] Batch generation complete'); } /** @@ -204,7 +204,7 @@ export async function generateAvatarsForCharacters(characterNames, onStarted = n * @returns {Promise} New avatar URL or null if failed */ export async function regenerateAvatar(characterName) { - console.log('[RPG Avatar] Regenerating avatar for:', characterName); + // console.log('[RPG Avatar] Regenerating avatar for:', characterName); // Mark as pending immediately pendingGenerations.add(characterName); @@ -245,13 +245,13 @@ async function generateAvatarPrompt(characterName) { } try { - console.log('[RPG Avatar] Generating LLM prompt for:', characterName); + // console.log('[RPG Avatar] Generating LLM prompt for:', characterName); const promptMessages = await generateAvatarPromptGenerationPrompt(characterName); let response; if (extensionSettings.generationMode === 'external') { - console.log('[RPG Avatar] Using external API for avatar prompt generation'); + // console.log('[RPG Avatar] Using external API for avatar prompt generation'); response = await generateWithExternalAPI(promptMessages); } else { response = await generateRaw({ @@ -262,7 +262,7 @@ async function generateAvatarPrompt(characterName) { if (response) { const prompt = response.trim(); - console.log(`[RPG Avatar] Generated prompt for ${characterName}:`, prompt); + // console.log(`[RPG Avatar] Generated prompt for ${characterName}:`, prompt); // Store prompt in session storage setSessionAvatarPrompt(characterName, prompt); @@ -313,11 +313,11 @@ async function generateSingleAvatar(characterName, prompt = null) { } if (!prompt) { - console.log(`[RPG Avatar] No LLM prompt for ${characterName}, using fallback prompt`); + // console.log(`[RPG Avatar] No LLM prompt for ${characterName}, using fallback prompt`); prompt = buildFallbackPrompt(characterName); } - console.log(`[RPG Avatar] Starting image generation for: ${characterName}`); + // console.log(`[RPG Avatar] Starting image generation for: ${characterName}`); try { // Execute /sd command with quiet=true to suppress chat output @@ -337,7 +337,7 @@ async function generateSingleAvatar(characterName, prompt = null) { extensionSettings.npcAvatars[characterName] = imageUrl; saveSettings(); - console.log(`[RPG Avatar] Successfully generated avatar for: ${characterName}`); + // console.log(`[RPG Avatar] Successfully generated avatar for: ${characterName}`); return imageUrl; } else { console.warn(`[RPG Avatar] Failed to extract image URL for ${characterName}:`, result); diff --git a/src/systems/features/chapterCheckpoint.js b/src/systems/features/chapterCheckpoint.js index 5ac2c41..4c3c612 100644 --- a/src/systems/features/chapterCheckpoint.js +++ b/src/systems/features/chapterCheckpoint.js @@ -49,7 +49,7 @@ export async function setChapterCheckpoint(messageId) { if (previousCheckpoint !== null && previousCheckpoint !== undefined && previousCheckpoint !== messageId && currentlyHiddenRange !== null) { const { start, end } = currentlyHiddenRange; await executeSlashCommandsOnChatInput(`/unhide ${start}-${end}`, { quiet: true }); - console.log(`[RPG Companion] Unhid previous range: ${start}-${end}`); + // console.log(`[RPG Companion] Unhid previous range: ${start}-${end}`); } // Store in chat metadata (this automatically overrides any previous checkpoint) @@ -61,13 +61,13 @@ export async function setChapterCheckpoint(messageId) { const rangeEnd = messageId - 1; await executeSlashCommandsOnChatInput(`/hide 0-${rangeEnd}`, { quiet: true }); currentlyHiddenRange = { start: 0, end: rangeEnd }; - console.log(`[RPG Companion] Hidden messages 0-${rangeEnd} (checkpoint at ${messageId})`); + // console.log(`[RPG Companion] Hidden messages 0-${rangeEnd} (checkpoint at ${messageId})`); } if (previousCheckpoint !== null && previousCheckpoint !== undefined && previousCheckpoint !== messageId) { - console.log(`[RPG Companion] Chapter checkpoint moved from message ${previousCheckpoint} to ${messageId}`); + // console.log(`[RPG Companion] Chapter checkpoint moved from message ${previousCheckpoint} to ${messageId}`); } else { - console.log('[RPG Companion] Chapter checkpoint set at message', messageId); + // console.log('[RPG Companion] Chapter checkpoint set at message', messageId); } // Emit event for UI updates @@ -91,14 +91,14 @@ export async function clearChapterCheckpoint() { if (currentlyHiddenRange !== null) { const { start, end } = currentlyHiddenRange; await executeSlashCommandsOnChatInput(`/unhide ${start}-${end}`, { quiet: true }); - console.log(`[RPG Companion] Unhid messages ${start}-${end}`); + // console.log(`[RPG Companion] Unhid messages ${start}-${end}`); currentlyHiddenRange = null; } delete chat_metadata.rpg_companion_chapter_checkpoint; saveChatDebounced(); - console.log('[RPG Companion] Chapter checkpoint cleared'); + // console.log('[RPG Companion] Chapter checkpoint cleared'); // Emit event for UI updates if (typeof document !== 'undefined') { @@ -173,7 +173,7 @@ export async function restoreCheckpointOnLoad() { if (needsRestore) { await executeSlashCommandsOnChatInput(`/hide 0-${rangeEnd}`, { quiet: true }); currentlyHiddenRange = { start: 0, end: rangeEnd }; - console.log(`[RPG Companion] Restored checkpoint: Hidden messages 0-${rangeEnd}`); + // console.log(`[RPG Companion] Restored checkpoint: Hidden messages 0-${rangeEnd}`); } else { currentlyHiddenRange = { start: 0, end: rangeEnd }; } diff --git a/src/systems/features/htmlCleaning.js b/src/systems/features/htmlCleaning.js index 24f1d86..371496a 100644 --- a/src/systems/features/htmlCleaning.js +++ b/src/systems/features/htmlCleaning.js @@ -63,7 +63,7 @@ export async function ensureHtmlCleaningRegex(st_extension_settings, saveSetting ); if (alreadyExists) { - console.log('[RPG Companion] HTML cleaning regex already exists, skipping import'); + // console.log('[RPG Companion] HTML cleaning regex already exists, skipping import'); return; } @@ -107,7 +107,7 @@ export async function ensureHtmlCleaningRegex(st_extension_settings, saveSetting console.warn('[RPG Companion] saveSettingsDebounced is not a function, cannot save HTML regex'); } - console.log('[RPG Companion] โœ… HTML cleaning regex imported successfully'); + // console.log('[RPG Companion] โœ… HTML cleaning regex imported successfully'); } catch (error) { console.error('[RPG Companion] Failed to import HTML cleaning regex:', error); console.error('[RPG Companion] Error details:', error.message, error.stack); @@ -145,7 +145,7 @@ export async function ensureTrackerCleaningRegex(st_extension_settings, saveSett ); if (alreadyExists) { - console.log('[RPG Companion] Tracker cleaning regex already exists, skipping import'); + // console.log('[RPG Companion] Tracker cleaning regex already exists, skipping import'); return; } @@ -190,7 +190,7 @@ export async function ensureTrackerCleaningRegex(st_extension_settings, saveSett console.warn('[RPG Companion] saveSettingsDebounced is not a function, cannot save tracker cleaning regex'); } - console.log('[RPG Companion] โœ… Tracker cleaning regex imported successfully'); + // console.log('[RPG Companion] โœ… Tracker cleaning regex imported successfully'); } catch (error) { console.error('[RPG Companion] Failed to import tracker cleaning regex:', error); console.error('[RPG Companion] Error details:', error.message, error.stack); diff --git a/src/systems/features/jsonCleaning.js b/src/systems/features/jsonCleaning.js index 797b2d6..e8721c4 100644 --- a/src/systems/features/jsonCleaning.js +++ b/src/systems/features/jsonCleaning.js @@ -32,11 +32,11 @@ export async function ensureJsonCleaningRegex(st_extension_settings, saveSetting ); if (alreadyExists) { - console.log('[RPG Companion] JSON cleaning regex already exists, skipping import'); + // console.log('[RPG Companion] JSON cleaning regex already exists, skipping import'); return; } - console.log('[RPG Companion] Importing JSON cleaning regex for Together mode...'); + // console.log('[RPG Companion] Importing JSON cleaning regex for Together mode...'); // Generate a UUID for the script const uuidv4 = () => { @@ -82,8 +82,8 @@ export async function ensureJsonCleaningRegex(st_extension_settings, saveSetting console.warn('[RPG Companion] saveSettingsDebounced is not a function, cannot save JSON cleaning regex'); } - console.log('[RPG Companion] โœ… JSON cleaning regex imported successfully'); - console.log('[RPG Companion] This regex will automatically remove tracker JSON from Together mode messages'); + // console.log('[RPG Companion] โœ… JSON cleaning regex imported successfully'); + // console.log('[RPG Companion] This regex will automatically remove tracker JSON from Together mode messages'); } catch (error) { console.error('[RPG Companion] Failed to import JSON cleaning regex:', error); console.error('[RPG Companion] Error details:', error.message, error.stack); @@ -111,7 +111,7 @@ export function removeJsonCleaningRegex(st_extension_settings, saveSettingsDebou ); if (st_extension_settings.regex.length < initialLength) { - console.log('[RPG Companion] Removed JSON cleaning regex'); + // console.log('[RPG Companion] Removed JSON cleaning regex'); if (typeof saveSettingsDebounced === 'function') { saveSettingsDebounced(); } diff --git a/src/systems/features/musicPlayer.js b/src/systems/features/musicPlayer.js index 3eac421..745ea80 100644 --- a/src/systems/features/musicPlayer.js +++ b/src/systems/features/musicPlayer.js @@ -52,11 +52,11 @@ export function parseAndStoreSpotifyUrl(responseText) { if (!extensionSettings.enableSpotifyMusic) return false; const songData = extractSpotifyUrl(responseText); - console.log('[RPG Companion] Spotify Parser: Found song:', songData); + // console.log('[RPG Companion] Spotify Parser: Found song:', songData); if (songData) { // Store in committed tracker data committedTrackerData.spotifyUrl = songData; - console.log('[RPG Companion] Spotify Parser: Stored song in committedTrackerData:', committedTrackerData.spotifyUrl); + // console.log('[RPG Companion] Spotify Parser: Stored song in committedTrackerData:', committedTrackerData.spotifyUrl); return true; } diff --git a/src/systems/generation/apiClient.js b/src/systems/generation/apiClient.js index d82e566..0d206bd 100644 --- a/src/systems/generation/apiClient.js +++ b/src/systems/generation/apiClient.js @@ -62,7 +62,7 @@ export async function generateWithExternalAPI(messages) { const normalizedBaseUrl = baseUrl.trim().replace(/\/+$/, ''); const endpoint = `${normalizedBaseUrl}/chat/completions`; - console.log(`[RPG Companion] Calling external API: ${normalizedBaseUrl} with model: ${model}`); + // console.log(`[RPG Companion] Calling external API: ${normalizedBaseUrl} with model: ${model}`); try { const response = await fetch(endpoint, { @@ -103,7 +103,7 @@ export async function generateWithExternalAPI(messages) { } const content = data.choices[0].message.content; - console.log('[RPG Companion] External API response received successfully'); + // console.log('[RPG Companion] External API response received successfully'); return content; } catch (error) { @@ -242,7 +242,7 @@ export async function updateRPGData(renderUserStats, renderInfoBox, renderThough let response; if (isExternalMode) { // External mode: Use external OpenAI-compatible API directly - console.log('[RPG Companion] Using external API for tracker generation'); + // console.log('[RPG Companion] Using external API for tracker generation'); response = await generateWithExternalAPI(prompt); } else { // Separate mode: Use SillyTavern's generateRaw @@ -256,6 +256,11 @@ export async function updateRPGData(renderUserStats, renderInfoBox, renderThough // console.log('[RPG Companion] Raw AI response:', response); const parsedData = parseResponse(response); + // Check if parsing completely failed (no tracker data found) + if (parsedData.parsingFailed) { + toastr.error(i18n.getTranslation('errors.parsingError'), '', { timeOut: 5000 }); + } + // Remove locks from parsed data (JSON format only, text format is unaffected) if (parsedData.userStats) { parsedData.userStats = removeLocks(parsedData.userStats); @@ -358,17 +363,17 @@ export async function updateRPGData(renderUserStats, renderInfoBox, renderThough if (extensionSettings.autoGenerateAvatars) { const charactersNeedingAvatars = parseCharactersFromThoughts(parsedData.characterThoughts); if (charactersNeedingAvatars.length > 0) { - console.log('[RPG Companion] Generating avatars for:', charactersNeedingAvatars); + // console.log('[RPG Companion] Generating avatars for:', charactersNeedingAvatars); // Generate avatars - this awaits completion await generateAvatarsForCharacters(charactersNeedingAvatars, (names) => { // Callback when generation starts - re-render to show loading spinners - console.log('[RPG Companion] Avatar generation started, showing spinners...'); + // console.log('[RPG Companion] Avatar generation started, showing spinners...'); renderThoughts(); }); // Re-render once all avatars are generated - console.log('[RPG Companion] All avatars generated, re-rendering...'); + // console.log('[RPG Companion] All avatars generated, re-rendering...'); renderThoughts(); } } diff --git a/src/systems/generation/encounterPrompts.js b/src/systems/generation/encounterPrompts.js index 2bda585..3f5b54d 100644 --- a/src/systems/generation/encounterPrompts.js +++ b/src/systems/generation/encounterPrompts.js @@ -97,14 +97,14 @@ export async function buildEncounterInitPrompt() { try { // Debug logging - console.log('[RPG Companion] Checking world info:', { - hasWindowGetWorldInfoPrompt: typeof window.getWorldInfoPrompt === 'function', - hasContextGetWorldInfoPrompt: typeof context.getWorldInfoPrompt === 'function', - chatLength: chat?.length, - contextChatLength: context.chat?.length, - hasActivatedWorldInfo: !!context.activatedWorldInfo, - activatedWorldInfoLength: context.activatedWorldInfo?.length - }); + // console.log('[RPG Companion] Checking world info:', { + // hasWindowGetWorldInfoPrompt: typeof window.getWorldInfoPrompt === 'function', + // hasContextGetWorldInfoPrompt: typeof context.getWorldInfoPrompt === 'function', + // chatLength: chat?.length, + // contextChatLength: context.chat?.length, + // hasActivatedWorldInfo: !!context.activatedWorldInfo, + // activatedWorldInfoLength: context.activatedWorldInfo?.length + // }); // Use SillyTavern's getWorldInfoPrompt to get activated lorebook entries // Try context.getWorldInfoPrompt first, then window.getWorldInfoPrompt @@ -114,20 +114,20 @@ export async function buildEncounterInitPrompt() { if (typeof getWorldInfoFn === 'function' && currentChat && currentChat.length > 0) { const chatForWI = currentChat.map(x => x.mes || x.message || x).filter(m => m && typeof m === 'string'); - console.log('[RPG Companion] Calling getWorldInfoPrompt with', chatForWI.length, 'messages'); + // console.log('[RPG Companion] Calling getWorldInfoPrompt with', chatForWI.length, 'messages'); const result = await getWorldInfoFn(chatForWI, 8000, false); const worldInfoString = result?.worldInfoString || result; - console.log('[RPG Companion] World info result:', { worldInfoString, length: worldInfoString?.length }); + // console.log('[RPG Companion] World info result:', { worldInfoString, length: worldInfoString?.length }); if (worldInfoString && worldInfoString.trim()) { systemMessage += worldInfoString.trim(); worldInfoAdded = true; - console.log('[RPG Companion] โœ… Added world info from getWorldInfoPrompt'); + // console.log('[RPG Companion] โœ… Added world info from getWorldInfoPrompt'); } } else { - console.log('[RPG Companion] getWorldInfoPrompt not available or no chat'); + // console.log('[RPG Companion] getWorldInfoPrompt not available or no chat'); } } catch (e) { console.warn('[RPG Companion] Failed to get world info from getWorldInfoPrompt:', e); @@ -135,7 +135,7 @@ export async function buildEncounterInitPrompt() { // Fallback to activatedWorldInfo if (!worldInfoAdded && context.activatedWorldInfo && Array.isArray(context.activatedWorldInfo) && context.activatedWorldInfo.length > 0) { - console.log('[RPG Companion] Using fallback activatedWorldInfo:', context.activatedWorldInfo.length, 'entries'); + // console.log('[RPG Companion] Using fallback activatedWorldInfo:', context.activatedWorldInfo.length, 'entries'); context.activatedWorldInfo.forEach((entry) => { if (entry && entry.content) { systemMessage += `${entry.content}\n\n`; @@ -745,7 +745,7 @@ export function parseEncounterJSON(response) { const repaired = repairJSON(cleaned); if (repaired) { - console.log('[RPG Companion] โœ“ Successfully repaired encounter JSON'); + // console.log('[RPG Companion] โœ“ Successfully repaired encounter JSON'); return repaired; } diff --git a/src/systems/generation/injector.js b/src/systems/generation/injector.js index 072ea7d..a524cb6 100644 --- a/src/systems/generation/injector.js +++ b/src/systems/generation/injector.js @@ -44,15 +44,15 @@ let lastCommittedChatLength = -1; export async function onGenerationStarted(type, data, dryRun) { // Skip dry runs (page reload, prompt manager preview, etc.) if (dryRun) { - console.log('[RPG Companion] Skipping onGenerationStarted: dry run detected'); + // console.log('[RPG Companion] Skipping onGenerationStarted: dry run detected'); return; } - console.log('[RPG Companion] onGenerationStarted called'); - console.log('[RPG Companion] enabled:', extensionSettings.enabled); - console.log('[RPG Companion] generationMode:', extensionSettings.generationMode); - console.log('[RPG Companion] โšก EVENT: onGenerationStarted - lastActionWasSwipe =', lastActionWasSwipe, '| isGenerating =', isGenerating); - console.log('[RPG Companion] Committed Prompt:', committedTrackerData); + // console.log('[RPG Companion] onGenerationStarted called'); + // console.log('[RPG Companion] enabled:', extensionSettings.enabled); + // console.log('[RPG Companion] generationMode:', extensionSettings.generationMode); + // console.log('[RPG Companion] โšก EVENT: onGenerationStarted - lastActionWasSwipe =', lastActionWasSwipe, '| isGenerating =', isGenerating); + // console.log('[RPG Companion] Committed Prompt:', committedTrackerData); // Skip tracker injection for image generation requests if (data?.quietImage) { @@ -115,18 +115,18 @@ export async function onGenerationStarted(type, data, dryRun) { const shouldCommit = isUserMessage && !lastActionWasSwipe && currentChatLength !== lastCommittedChatLength; if (shouldCommit) { - console.log('[RPG Companion] ๐Ÿ“ TOGETHER MODE COMMIT: User sent message - committing data from BEFORE user message'); - console.log('[RPG Companion] Chat length:', currentChatLength, 'Last committed:', lastCommittedChatLength); - console.log('[RPG Companion] BEFORE: committedTrackerData =', { - userStats: committedTrackerData.userStats ? `${committedTrackerData.userStats.substring(0, 50)}...` : 'null', - infoBox: committedTrackerData.infoBox ? 'exists' : 'null', - characterThoughts: committedTrackerData.characterThoughts ? `${committedTrackerData.characterThoughts.substring(0, 100)}...` : 'null' - }); - console.log('[RPG Companion] BEFORE: lastGeneratedData =', { - userStats: lastGeneratedData.userStats ? `${lastGeneratedData.userStats.substring(0, 50)}...` : 'null', - infoBox: lastGeneratedData.infoBox ? 'exists' : 'null', - characterThoughts: lastGeneratedData.characterThoughts ? `${lastGeneratedData.characterThoughts.substring(0, 100)}...` : 'null' - }); + // console.log('[RPG Companion] ๐Ÿ“ TOGETHER MODE COMMIT: User sent message - committing data from BEFORE user message'); + // console.log('[RPG Companion] Chat length:', currentChatLength, 'Last committed:', lastCommittedChatLength); + // console.log('[RPG Companion] BEFORE: committedTrackerData =', { + // userStats: committedTrackerData.userStats ? `${committedTrackerData.userStats.substring(0, 50)}...` : 'null', + // infoBox: committedTrackerData.infoBox ? 'exists' : 'null', + // characterThoughts: committedTrackerData.characterThoughts ? `${committedTrackerData.characterThoughts.substring(0, 100)}...` : 'null' + // // }); + // console.log('[RPG Companion] BEFORE: lastGeneratedData =', { + // userStats: lastGeneratedData.userStats ? `${lastGeneratedData.userStats.substring(0, 50)}...` : 'null', + // infoBox: lastGeneratedData.infoBox ? 'exists' : 'null', + // characterThoughts: lastGeneratedData.characterThoughts ? `${lastGeneratedData.characterThoughts.substring(0, 100)}...` : 'null' + // }); // Commit displayed data (from before user sent message) committedTrackerData.userStats = lastGeneratedData.userStats; @@ -136,23 +136,23 @@ export async function onGenerationStarted(type, data, dryRun) { // Track chat length to prevent duplicate commits lastCommittedChatLength = currentChatLength; - console.log('[RPG Companion] AFTER: committedTrackerData =', { - userStats: committedTrackerData.userStats ? `${committedTrackerData.userStats.substring(0, 50)}...` : 'null', - infoBox: committedTrackerData.infoBox ? 'exists' : 'null', - characterThoughts: committedTrackerData.characterThoughts ? `${committedTrackerData.characterThoughts.substring(0, 100)}...` : 'null' - }); + // console.log('[RPG Companion] AFTER: committedTrackerData =', { + // userStats: committedTrackerData.userStats ? `${committedTrackerData.userStats.substring(0, 50)}...` : 'null', + // infoBox: committedTrackerData.infoBox ? 'exists' : 'null', + // characterThoughts: committedTrackerData.characterThoughts ? `${committedTrackerData.characterThoughts.substring(0, 100)}...` : 'null' + // }); } else if (lastActionWasSwipe) { - console.log('[RPG Companion] โญ๏ธ Skipping commit: swipe (using previous committed data)'); + // console.log('[RPG Companion] โญ๏ธ Skipping commit: swipe (using previous committed data)'); } else if (!isUserMessage) { - console.log('[RPG Companion] โญ๏ธ Skipping commit: second-to-last message is not user message (likely swipe or continuation)'); + // console.log('[RPG Companion] โญ๏ธ Skipping commit: second-to-last message is not user message (likely swipe or continuation)'); } - console.log('[RPG Companion] ๐Ÿ“ฆ TOGETHER MODE: Injecting committed tracker data into prompt'); - console.log('[RPG Companion] committedTrackerData =', { - userStats: committedTrackerData.userStats ? `${committedTrackerData.userStats.substring(0, 50)}...` : 'null', - infoBox: committedTrackerData.infoBox ? 'exists' : 'null', - characterThoughts: committedTrackerData.characterThoughts ? `${committedTrackerData.characterThoughts.substring(0, 100)}...` : 'null' - }); + // console.log('[RPG Companion] ๐Ÿ“ฆ TOGETHER MODE: Injecting committed tracker data into prompt'); + // console.log('[RPG Companion] committedTrackerData =', { + // userStats: committedTrackerData.userStats ? `${committedTrackerData.userStats.substring(0, 50)}...` : 'null', + // infoBox: committedTrackerData.infoBox ? 'exists' : 'null', + // characterThoughts: committedTrackerData.characterThoughts ? `${committedTrackerData.characterThoughts.substring(0, 100)}...` : 'null' + // }); } // For SEPARATE mode only: Check if we need to commit extension data @@ -162,35 +162,35 @@ export async function onGenerationStarted(type, data, dryRun) { if (extensionSettings.generationMode === 'separate' && !isGenerating) { if (!lastActionWasSwipe) { // User sent a new message - commit lastGeneratedData before generation - console.log('[RPG Companion] ๐Ÿ“ COMMIT: New message - committing lastGeneratedData'); - console.log('[RPG Companion] BEFORE commit - committedTrackerData:', { - userStats: committedTrackerData.userStats ? 'exists' : 'null', - infoBox: committedTrackerData.infoBox ? 'exists' : 'null', - characterThoughts: committedTrackerData.characterThoughts ? 'exists' : 'null' - }); - console.log('[RPG Companion] BEFORE commit - lastGeneratedData:', { - userStats: lastGeneratedData.userStats ? 'exists' : 'null', - infoBox: lastGeneratedData.infoBox ? 'exists' : 'null', - characterThoughts: lastGeneratedData.characterThoughts ? 'exists' : 'null' - }); + // console.log('[RPG Companion] ๐Ÿ“ COMMIT: New message - committing lastGeneratedData'); + // console.log('[RPG Companion] BEFORE commit - committedTrackerData:', { + // userStats: committedTrackerData.userStats ? 'exists' : 'null', + // infoBox: committedTrackerData.infoBox ? 'exists' : 'null', + // characterThoughts: committedTrackerData.characterThoughts ? 'exists' : 'null' + // // }); + // console.log('[RPG Companion] BEFORE commit - lastGeneratedData:', { + // userStats: lastGeneratedData.userStats ? 'exists' : 'null', + // infoBox: lastGeneratedData.infoBox ? 'exists' : 'null', + // characterThoughts: lastGeneratedData.characterThoughts ? 'exists' : 'null' + // }); committedTrackerData.userStats = lastGeneratedData.userStats; committedTrackerData.infoBox = lastGeneratedData.infoBox; committedTrackerData.characterThoughts = lastGeneratedData.characterThoughts; - console.log('[RPG Companion] AFTER commit - committedTrackerData:', { - userStats: committedTrackerData.userStats ? 'exists' : 'null', - infoBox: committedTrackerData.infoBox ? 'exists' : 'null', - characterThoughts: committedTrackerData.characterThoughts ? 'exists' : 'null' - }); + // console.log('[RPG Companion] AFTER commit - committedTrackerData:', { + // userStats: committedTrackerData.userStats ? 'exists' : 'null', + // infoBox: committedTrackerData.infoBox ? 'exists' : 'null', + // characterThoughts: committedTrackerData.characterThoughts ? 'exists' : 'null' + // }); // Reset flag after committing (ready for next cycle) } else { - console.log('[RPG Companion] ๐Ÿ”„ SWIPE: Using existing committedTrackerData (no commit)'); - console.log('[RPG Companion] committedTrackerData:', { - userStats: committedTrackerData.userStats ? 'exists' : 'null', - infoBox: committedTrackerData.infoBox ? 'exists' : 'null', - characterThoughts: committedTrackerData.characterThoughts ? 'exists' : 'null' - }); + // console.log('[RPG Companion] ๐Ÿ”„ SWIPE: Using existing committedTrackerData (no commit)'); + // console.log('[RPG Companion] committedTrackerData:', { + // userStats: committedTrackerData.userStats ? 'exists' : 'null', + // infoBox: committedTrackerData.infoBox ? 'exists' : 'null', + // characterThoughts: committedTrackerData.characterThoughts ? 'exists' : 'null' + // }); // Reset flag after using it (swipe generation complete, ready for next action) } } diff --git a/src/systems/generation/lockManager.js b/src/systems/generation/lockManager.js index 710fdf3..713bd6c 100644 --- a/src/systems/generation/lockManager.js +++ b/src/systems/generation/lockManager.js @@ -214,9 +214,9 @@ function applyInfoBoxLocks(data, lockedItems) { * @returns {string} JSON string with locks applied */ function applyCharactersLocks(data, lockedItems) { - console.log('[Lock Manager] applyCharactersLocks called'); - console.log('[Lock Manager] Locked items:', JSON.stringify(lockedItems, null, 2)); - console.log('[Lock Manager] Input data:', JSON.stringify(data, null, 2)); + // console.log('[Lock Manager] applyCharactersLocks called'); + // console.log('[Lock Manager] Locked items:', JSON.stringify(lockedItems, null, 2)); + // console.log('[Lock Manager] Input data:', JSON.stringify(data, null, 2)); // Handle both array format and object format let characters = Array.isArray(data) ? data : (data.characters || []); @@ -226,7 +226,7 @@ function applyCharactersLocks(data, lockedItems) { // Check if entire character is locked (index-based) if (lockedItems[index] === true) { - console.log('[Lock Manager] Locking entire character by index:', index); + // console.log('[Lock Manager] Locking entire character by index:', index); return { ...char, locked: true }; } @@ -235,7 +235,7 @@ function applyCharactersLocks(data, lockedItems) { if (charLocks === true) { // Entire character is locked - console.log('[Lock Manager] Locking entire character:', charName); + // console.log('[Lock Manager] Locking entire character:', charName); return { ...char, locked: true }; } else if (charLocks && typeof charLocks === 'object') { // Character has field-level locks @@ -255,14 +255,14 @@ function applyCharactersLocks(data, lockedItems) { // Check at root level first (backward compatibility) if (modifiedChar[fieldName] !== undefined) { - console.log('[Lock Manager] Applying lock to field:', `${charName}.${fieldName}`); + // console.log('[Lock Manager] Applying lock to field:', `${charName}.${fieldName}`); modifiedChar[fieldName] = { value: modifiedChar[fieldName], locked: true }; locked = true; } else if (modifiedChar[snakeCaseFieldName] !== undefined) { - console.log('[Lock Manager] Applying lock to snake_case field:', `${charName}.${snakeCaseFieldName} (from ${fieldName})`); + // console.log('[Lock Manager] Applying lock to snake_case field:', `${charName}.${snakeCaseFieldName} (from ${fieldName})`); modifiedChar[snakeCaseFieldName] = { value: modifiedChar[snakeCaseFieldName], locked: true @@ -273,7 +273,7 @@ function applyCharactersLocks(data, lockedItems) { // Check in nested objects (details, relationship, thoughts) if (!locked && modifiedChar.details) { if (modifiedChar.details[fieldName] !== undefined) { - console.log('[Lock Manager] Applying lock to details field:', `${charName}.details.${fieldName}`); + // console.log('[Lock Manager] Applying lock to details field:', `${charName}.details.${fieldName}`); if (!modifiedChar.details || typeof modifiedChar.details !== 'object') { modifiedChar.details = {}; } else { @@ -285,7 +285,7 @@ function applyCharactersLocks(data, lockedItems) { }; locked = true; } else if (modifiedChar.details[snakeCaseFieldName] !== undefined) { - console.log('[Lock Manager] Applying lock to details snake_case field:', `${charName}.details.${snakeCaseFieldName} (from ${fieldName})`); + // console.log('[Lock Manager] Applying lock to details snake_case field:', `${charName}.details.${snakeCaseFieldName} (from ${fieldName})`); if (!modifiedChar.details || typeof modifiedChar.details !== 'object') { modifiedChar.details = {}; } else { @@ -302,7 +302,7 @@ function applyCharactersLocks(data, lockedItems) { // Check in relationship object if (!locked && modifiedChar.relationship) { if (modifiedChar.relationship[fieldName] !== undefined) { - console.log('[Lock Manager] Applying lock to relationship field:', `${charName}.relationship.${fieldName}`); + // console.log('[Lock Manager] Applying lock to relationship field:', `${charName}.relationship.${fieldName}`); modifiedChar.relationship = { ...modifiedChar.relationship }; modifiedChar.relationship[fieldName] = { value: modifiedChar.relationship[fieldName], @@ -310,7 +310,7 @@ function applyCharactersLocks(data, lockedItems) { }; locked = true; } else if (modifiedChar.relationship[snakeCaseFieldName] !== undefined) { - console.log('[Lock Manager] Applying lock to relationship snake_case field:', `${charName}.relationship.${snakeCaseFieldName} (from ${fieldName})`); + // console.log('[Lock Manager] Applying lock to relationship snake_case field:', `${charName}.relationship.${snakeCaseFieldName} (from ${fieldName})`); modifiedChar.relationship = { ...modifiedChar.relationship }; modifiedChar.relationship[snakeCaseFieldName] = { value: modifiedChar.relationship[snakeCaseFieldName], @@ -323,7 +323,7 @@ function applyCharactersLocks(data, lockedItems) { // Check in thoughts object if (!locked && modifiedChar.thoughts) { if (modifiedChar.thoughts[fieldName] !== undefined) { - console.log('[Lock Manager] Applying lock to thoughts field:', `${charName}.thoughts.${fieldName}`); + // console.log('[Lock Manager] Applying lock to thoughts field:', `${charName}.thoughts.${fieldName}`); modifiedChar.thoughts = { ...modifiedChar.thoughts }; modifiedChar.thoughts[fieldName] = { value: modifiedChar.thoughts[fieldName], @@ -331,7 +331,7 @@ function applyCharactersLocks(data, lockedItems) { }; locked = true; } else if (modifiedChar.thoughts[snakeCaseFieldName] !== undefined) { - console.log('[Lock Manager] Applying lock to thoughts snake_case field:', `${charName}.thoughts.${snakeCaseFieldName} (from ${fieldName})`); + // console.log('[Lock Manager] Applying lock to thoughts snake_case field:', `${charName}.thoughts.${snakeCaseFieldName} (from ${fieldName})`); modifiedChar.thoughts = { ...modifiedChar.thoughts }; modifiedChar.thoughts[snakeCaseFieldName] = { value: modifiedChar.thoughts[snakeCaseFieldName], @@ -354,7 +354,7 @@ function applyCharactersLocks(data, lockedItems) { ? JSON.stringify(characters, null, 2) : JSON.stringify({ ...data, characters }, null, 2); - console.log('[Lock Manager] Output data:', result); + // console.log('[Lock Manager] Output data:', result); return result; } @@ -429,7 +429,7 @@ export function isItemLocked(trackerType, itemPath) { * @param {boolean} locked - New lock state */ export function setItemLock(trackerType, itemPath, locked) { - console.log('[Lock Manager] setItemLock called:', { trackerType, itemPath, locked }); + // console.log('[Lock Manager] setItemLock called:', { trackerType, itemPath, locked }); if (!extensionSettings.lockedItems) { extensionSettings.lockedItems = {}; @@ -459,5 +459,5 @@ export function setItemLock(trackerType, itemPath, locked) { delete current[finalKey]; } - console.log('[Lock Manager] Locked items after set:', JSON.stringify(extensionSettings.lockedItems, null, 2)); + // console.log('[Lock Manager] Locked items after set:', JSON.stringify(extensionSettings.lockedItems, null, 2)); } diff --git a/src/systems/generation/parser.js b/src/systems/generation/parser.js index a5824e1..f0bdd05 100644 --- a/src/systems/generation/parser.js +++ b/src/systems/generation/parser.js @@ -129,7 +129,7 @@ function stripBrackets(text) { * Helper to log to both console and debug logs array */ function debugLog(message, data = null) { - console.log(message, data || ''); + // console.log(message, data || ''); if (extensionSettings.debugMode) { addDebugLog(message, data); } @@ -209,30 +209,30 @@ export function parseResponse(responseText) { } if (extractedObjects.length > 0) { - console.log(`[RPG Parser] โœ“ Found ${extractedObjects.length} raw JSON objects (v3 format)`); + // console.log(`[RPG Parser] โœ“ Found ${extractedObjects.length} raw JSON objects (v3 format)`); debugLog(`[RPG Parser] โœ“ Found ${extractedObjects.length} raw JSON objects (v3 format)`); // First, try to parse as unified JSON structure (new v3.1 format) if (extractedObjects.length === 1) { const parsed = repairJSON(extractedObjects[0]); if (parsed && (parsed.userStats || parsed.infoBox || parsed.characters)) { - console.log('[RPG Parser] โœ“ Detected unified JSON structure (v3.1 format)'); + // console.log('[RPG Parser] โœ“ Detected unified JSON structure (v3.1 format)'); if (parsed.userStats) { result.userStats = JSON.stringify(parsed.userStats); - console.log('[RPG Parser] โœ“ Extracted userStats from unified structure'); + // console.log('[RPG Parser] โœ“ Extracted userStats from unified structure'); } if (parsed.infoBox) { result.infoBox = JSON.stringify(parsed.infoBox); - console.log('[RPG Parser] โœ“ Extracted infoBox from unified structure'); + // console.log('[RPG Parser] โœ“ Extracted infoBox from unified structure'); } if (parsed.characters) { result.characterThoughts = JSON.stringify(parsed.characters); - console.log('[RPG Parser] โœ“ Extracted characters from unified structure'); + // console.log('[RPG Parser] โœ“ Extracted characters from unified structure'); } if (result.userStats || result.infoBox || result.characterThoughts) { - console.log('[RPG Parser] โœ“ Returning unified JSON parse results'); + // console.log('[RPG Parser] โœ“ Returning unified JSON parse results'); debugLog('[RPG Parser] Returning unified JSON parse results'); return result; } @@ -242,13 +242,13 @@ export function parseResponse(responseText) { // Fall back to parsing multiple separate JSON objects (legacy v3.0 format) for (let idx = 0; idx < extractedObjects.length; idx++) { const jsonContent = extractedObjects[idx]; - console.log(`[RPG Parser] Parsing object ${idx + 1}:`, jsonContent.substring(0, 100) + '...'); - console.log(`[RPG Parser] Full object ${idx + 1} length:`, jsonContent.length); + // console.log(`[RPG Parser] Parsing object ${idx + 1}:`, jsonContent.substring(0, 100) + '...'); + // console.log(`[RPG Parser] Full object ${idx + 1} length:`, jsonContent.length); const parsed = repairJSON(jsonContent); if (parsed) { - console.log(`[RPG Parser] Object ${idx + 1} parsed successfully, keys:`, Object.keys(parsed)); + // console.log(`[RPG Parser] Object ${idx + 1} parsed successfully, keys:`, Object.keys(parsed)); // Check if object is wrapped (e.g., {"userStats": {...}}) // Unwrap single-key objects that match our tracker types @@ -257,22 +257,22 @@ export function parseResponse(responseText) { const key = Object.keys(parsed)[0]; if (key === 'userStats' || key === 'infoBox' || key === 'characters') { unwrapped = parsed[key]; - console.log(`[RPG Parser] โœ“ Unwrapped ${key} object`); + // console.log(`[RPG Parser] โœ“ Unwrapped ${key} object`); } } // Detect tracker type by checking for top-level fields if (unwrapped.stats || unwrapped.status || unwrapped.skills || unwrapped.inventory || unwrapped.quests) { result.userStats = jsonContent; - console.log('[RPG Parser] โœ“ Assigned to User Stats'); + // console.log('[RPG Parser] โœ“ Assigned to User Stats'); debugLog('[RPG Parser] โœ“ Extracted raw JSON User Stats'); } else if (unwrapped.date || unwrapped.location || unwrapped.weather || unwrapped.temperature || unwrapped.time) { result.infoBox = jsonContent; - console.log('[RPG Parser] โœ“ Assigned to Info Box'); + // console.log('[RPG Parser] โœ“ Assigned to Info Box'); debugLog('[RPG Parser] โœ“ Extracted raw JSON Info Box'); } else if (unwrapped.characters || Array.isArray(unwrapped)) { result.characterThoughts = jsonContent; - console.log('[RPG Parser] โœ“ Assigned to Characters'); + // console.log('[RPG Parser] โœ“ Assigned to Characters'); debugLog('[RPG Parser] โœ“ Extracted raw JSON Characters'); } else { console.warn('[RPG Parser] โš ๏ธ Could not categorize object with keys:', Object.keys(parsed)); @@ -283,11 +283,11 @@ export function parseResponse(responseText) { } if (result.userStats || result.infoBox || result.characterThoughts) { - console.log('[RPG Parser] โœ“ Returning raw JSON parse results:', { - hasUserStats: !!result.userStats, - hasInfoBox: !!result.infoBox, - hasCharacters: !!result.characterThoughts - }); + // console.log('[RPG Parser] โœ“ Returning raw JSON parse results:', { + // hasUserStats: !!result.userStats, + // hasInfoBox: !!result.infoBox, + // hasCharacters: !!result.characterThoughts + // }); debugLog('[RPG Parser] Returning raw JSON parse results'); return result; } else { @@ -301,31 +301,31 @@ export function parseResponse(responseText) { const jsonMatches = [...cleanedResponse.matchAll(jsonBlockRegex)]; if (jsonMatches.length > 0) { - console.log('[RPG Parser] โœ“ Found', jsonMatches.length, 'JSON code blocks (v3 format with fences)'); + // console.log('[RPG Parser] โœ“ Found', jsonMatches.length, 'JSON code blocks (v3 format with fences)'); debugLog('[RPG Parser] โœ“ Found JSON code blocks (v3 format), parsing as JSON'); for (let idx = 0; idx < jsonMatches.length; idx++) { const match = jsonMatches[idx]; const jsonContent = match[1].trim(); - console.log(`[RPG Parser] Parsing JSON block ${idx + 1}:`, jsonContent.substring(0, 100) + '...'); + // console.log(`[RPG Parser] Parsing JSON block ${idx + 1}:`, jsonContent.substring(0, 100) + '...'); const parsed = repairJSON(jsonContent); if (parsed) { - console.log(`[RPG Parser] JSON block ${idx + 1} parsed successfully, keys:`, Object.keys(parsed)); + // console.log(`[RPG Parser] JSON block ${idx + 1} parsed successfully, keys:`, Object.keys(parsed)); // Detect tracker type by checking for top-level fields if (parsed.stats || parsed.status || parsed.skills || parsed.inventory || parsed.quests) { result.userStats = jsonContent; - console.log('[RPG Parser] โœ“ Assigned to User Stats'); + // console.log('[RPG Parser] โœ“ Assigned to User Stats'); debugLog('[RPG Parser] โœ“ Extracted JSON User Stats'); } else if (parsed.date || parsed.location || parsed.weather || parsed.temperature || parsed.time) { result.infoBox = jsonContent; - console.log('[RPG Parser] โœ“ Assigned to Info Box'); + // console.log('[RPG Parser] โœ“ Assigned to Info Box'); debugLog('[RPG Parser] โœ“ Extracted JSON Info Box'); } else if (parsed.characters || Array.isArray(parsed)) { result.characterThoughts = jsonContent; - console.log('[RPG Parser] โœ“ Assigned to Characters'); + // console.log('[RPG Parser] โœ“ Assigned to Characters'); debugLog('[RPG Parser] โœ“ Extracted JSON Characters'); } else { console.warn('[RPG Parser] โš ๏ธ Could not categorize JSON block with keys:', Object.keys(parsed)); @@ -339,11 +339,11 @@ export function parseResponse(responseText) { // If we found at least one valid JSON block, return the result // Mixed formats (some JSON, some text) will still work if (result.userStats || result.infoBox || result.characterThoughts) { - console.log('[RPG Parser] โœ“ Returning JSON code block parse results:', { - hasUserStats: !!result.userStats, - hasInfoBox: !!result.infoBox, - hasCharacters: !!result.characterThoughts - }); + // console.log('[RPG Parser] โœ“ Returning JSON code block parse results:', { + // hasUserStats: !!result.userStats, + // hasInfoBox: !!result.infoBox, + // hasCharacters: !!result.characterThoughts + // }); debugLog('[RPG Parser] Returning JSON parse results'); return result; } else { @@ -500,6 +500,12 @@ export function parseResponse(responseText) { debugLog('[RPG Parser] Found Characters:', !!result.characterThoughts); debugLog('[RPG Parser] ======================================================='); + // Check if we found at least one section - if not, mark as parsing failure + if (!result.userStats && !result.infoBox && !result.characterThoughts) { + result.parsingFailed = true; + console.error('[RPG Parser] โŒ No tracker data found in response - parsing failed'); + } + return result; } // End parseResponse @@ -525,25 +531,25 @@ export function parseUserStats(statsText) { // Extract stats from v3 JSON structure if (statsData.stats && Array.isArray(statsData.stats)) { - console.log('[RPG Parser] โœ“ Extracting stats array, count:', statsData.stats.length); + // console.log('[RPG Parser] โœ“ Extracting stats array, count:', statsData.stats.length); statsData.stats.forEach(stat => { if (stat.id && typeof stat.value !== 'undefined') { extensionSettings.userStats[stat.id] = stat.value; - console.log(`[RPG Parser] โœ“ Set ${stat.id} = ${stat.value}`); + // console.log(`[RPG Parser] โœ“ Set ${stat.id} = ${stat.value}`); } }); } // Extract status if (statsData.status) { - console.log('[RPG Parser] โœ“ Extracting status:', statsData.status); + // console.log('[RPG Parser] โœ“ Extracting status:', statsData.status); if (statsData.status.mood) { extensionSettings.userStats.mood = statsData.status.mood; - console.log('[RPG Parser] โœ“ Set mood =', statsData.status.mood); + // console.log('[RPG Parser] โœ“ Set mood =', statsData.status.mood); } if (statsData.status.conditions) { extensionSettings.userStats.conditions = statsData.status.conditions; - console.log('[RPG Parser] โœ“ Set conditions =', statsData.status.conditions); + // console.log('[RPG Parser] โœ“ Set conditions =', statsData.status.conditions); } } @@ -587,7 +593,7 @@ export function parseUserStats(statsText) { stored: convertStoredInventory(inv.stored), assets: convertItems(inv.assets) }; - console.log('[RPG Parser] โœ“ Converted v3 inventory:', extensionSettings.userStats.inventory); + // console.log('[RPG Parser] โœ“ Converted v3 inventory:', extensionSettings.userStats.inventory); } // Extract quests (convert v3 object format to v2 string format) @@ -609,13 +615,13 @@ export function parseUserStats(statsText) { ? statsData.quests.optional.map(convertQuest) : [] }; - console.log('[RPG Parser] โœ“ Converted v3 quests:', extensionSettings.quests); + // console.log('[RPG Parser] โœ“ Converted v3 quests:', extensionSettings.quests); } // Extract skills if present (store as object, not JSON string) if (statsData.skills && Array.isArray(statsData.skills)) { extensionSettings.userStats.skills = statsData.skills; - console.log('[RPG Parser] โœ“ Set skills:', extensionSettings.userStats.skills); + // console.log('[RPG Parser] โœ“ Set skills:', extensionSettings.userStats.skills); } debugLog('[RPG Parser] โœ“ Successfully extracted v3 JSON data'); diff --git a/src/systems/generation/promptBuilder.js b/src/systems/generation/promptBuilder.js index 57513f1..e10e6ed 100644 --- a/src/systems/generation/promptBuilder.js +++ b/src/systems/generation/promptBuilder.js @@ -85,7 +85,7 @@ async function getCharacterCardsInfo() { // Filter out disabled (muted) members const disabledMembers = group?.disabled_members || []; - console.log('[RPG Companion] ๐Ÿ” Group ID:', selected_group, '| Disabled members:', disabledMembers); + // console.log('[RPG Companion] ๐Ÿ” Group ID:', selected_group, '| Disabled members:', disabledMembers); let characterIndex = 0; groupMembers.forEach((member) => { @@ -93,7 +93,7 @@ async function getCharacterCardsInfo() { // Skip muted characters - check against avatar filename if (member.avatar && disabledMembers.includes(member.avatar)) { - console.log(`[RPG Companion] โŒ Skipping muted: ${member.name} (${member.avatar})`); + // console.log(`[RPG Companion] โŒ Skipping muted: ${member.name} (${member.avatar})`); return; } @@ -236,16 +236,16 @@ export function generateTrackerExample() { // Build unified JSON structure with proper wrapper keys const parts = []; - console.log('[RPG Companion] generateTrackerExample - enabled modules:', { - showUserStats: extensionSettings.showUserStats, - showInfoBox: extensionSettings.showInfoBox, - showCharacterThoughts: extensionSettings.showCharacterThoughts - }); - console.log('[RPG Companion] generateTrackerExample - committed data:', { - hasUserStats: !!committedTrackerData.userStats, - hasInfoBox: !!committedTrackerData.infoBox, - hasCharacterThoughts: !!committedTrackerData.characterThoughts - }); + // console.log('[RPG Companion] generateTrackerExample - enabled modules:', { + // showUserStats: extensionSettings.showUserStats, + // showInfoBox: extensionSettings.showInfoBox, + // showCharacterThoughts: extensionSettings.showCharacterThoughts + // // }); + // console.log('[RPG Companion] generateTrackerExample - committed data:', { + // hasUserStats: !!committedTrackerData.userStats, + // hasInfoBox: !!committedTrackerData.infoBox, + // hasCharacterThoughts: !!committedTrackerData.characterThoughts + // }); if (extensionSettings.showUserStats && committedTrackerData.userStats) { // Try to parse as JSON first, otherwise treat as text @@ -285,7 +285,7 @@ export function generateTrackerExample() { example = '{\n' + parts.join(',\n') + '\n}'; } - console.log('[RPG Companion] generateTrackerExample - result length:', example.length, 'parts:', parts.length); + // console.log('[RPG Companion] generateTrackerExample - result length:', example.length, 'parts:', parts.length); return example.trim(); } diff --git a/src/systems/integration/sillytavern.js b/src/systems/integration/sillytavern.js index 00a063f..81974bb 100644 --- a/src/systems/integration/sillytavern.js +++ b/src/systems/integration/sillytavern.js @@ -21,6 +21,7 @@ import { $musicPlayerContainer } from '../../core/state.js'; import { saveChatData, loadChatData } from '../../core/persistence.js'; +import { i18n } from '../../core/i18n.js'; // Generation & Parsing import { parseResponse, parseUserStats } from '../generation/parser.js'; @@ -88,7 +89,7 @@ export function commitTrackerData() { export function onMessageSent() { if (!extensionSettings.enabled) return; - console.log('[RPG Companion] ๐ŸŸข EVENT: onMessageSent - lastActionWasSwipe =', lastActionWasSwipe); + // console.log('[RPG Companion] ๐ŸŸข EVENT: onMessageSent - lastActionWasSwipe =', lastActionWasSwipe); // Check if this is a streaming placeholder message (content = "...") // When streaming is on, ST sends a "..." placeholder before generation starts @@ -97,12 +98,12 @@ export function onMessageSent() { const lastMessage = chat && chat.length > 0 ? chat[chat.length - 1] : null; if (lastMessage && lastMessage.mes === '...') { - console.log('[RPG Companion] ๐ŸŸข Ignoring onMessageSent: streaming placeholder message'); + // console.log('[RPG Companion] ๐ŸŸข Ignoring onMessageSent: streaming placeholder message'); return; } - console.log('[RPG Companion] ๐ŸŸข EVENT: onMessageSent (after placeholder check)'); - console.log('[RPG Companion] ๐ŸŸข NOTE: lastActionWasSwipe will be reset in onMessageReceived after generation completes'); + // console.log('[RPG Companion] ๐ŸŸข EVENT: onMessageSent (after placeholder check)'); + // console.log('[RPG Companion] ๐ŸŸข NOTE: lastActionWasSwipe will be reset in onMessageReceived after generation completes'); // For separate mode with auto-update disabled, commit displayed tracker if (extensionSettings.generationMode === 'separate' && !extensionSettings.autoUpdate) { @@ -111,7 +112,7 @@ export function onMessageSent() { committedTrackerData.infoBox = lastGeneratedData.infoBox; committedTrackerData.characterThoughts = lastGeneratedData.characterThoughts; - console.log('[RPG Companion] ๐Ÿ’พ SEPARATE MODE: Committed displayed tracker (auto-update disabled)'); + // console.log('[RPG Companion] ๐Ÿ’พ SEPARATE MODE: Committed displayed tracker (auto-update disabled)'); } } } @@ -120,7 +121,7 @@ export function onMessageSent() { * Event handler for when a message is generated. */ export async function onMessageReceived(data) { - console.log('[RPG Companion] onMessageReceived called, lastActionWasSwipe:', lastActionWasSwipe); + // console.log('[RPG Companion] onMessageReceived called, lastActionWasSwipe:', lastActionWasSwipe); if (!extensionSettings.enabled) { return; @@ -129,7 +130,7 @@ export async function onMessageReceived(data) { // Reset swipe flag after generation completes // This ensures next user message (whether from original or swipe) triggers commit setLastActionWasSwipe(false); - console.log('[RPG Companion] ๐ŸŸข Reset lastActionWasSwipe = false (generation completed)'); + // console.log('[RPG Companion] ๐ŸŸข Reset lastActionWasSwipe = false (generation completed)'); if (extensionSettings.generationMode === 'together') { // In together mode, parse the response to extract RPG data @@ -139,6 +140,11 @@ export async function onMessageReceived(data) { const responseText = lastMessage.mes; const parsedData = parseResponse(responseText); + // Check if parsing completely failed (no tracker data found) + if (parsedData.parsingFailed) { + toastr.error(i18n.getTranslation('errors.parsingError'), '', { timeOut: 5000 }); + } + // Remove locks from parsed data (JSON format only, text format is unaffected) if (parsedData.userStats) { parsedData.userStats = removeLocks(parsedData.userStats); @@ -154,7 +160,7 @@ export async function onMessageReceived(data) { parseAndStoreSpotifyUrl(responseText); // Update display data with newly parsed response - console.log('[RPG Companion] ๐Ÿ“ TOGETHER MODE: Updating lastGeneratedData with parsed response'); + // console.log('[RPG Companion] ๐Ÿ“ TOGETHER MODE: Updating lastGeneratedData with parsed response'); if (parsedData.userStats) { lastGeneratedData.userStats = parsedData.userStats; parseUserStats(parsedData.userStats); @@ -227,8 +233,8 @@ export async function onMessageReceived(data) { // Save to chat metadata saveChatData(); } - } else if (extensionSettings.generationMode === 'separate') { - // In separate mode, also parse Spotify URLs from the main roleplay response + } else if (extensionSettings.generationMode === 'separate' || extensionSettings.generationMode === 'external') { + // In separate/external mode, also parse Spotify URLs from the main roleplay response const lastMessage = chat[chat.length - 1]; if (lastMessage && !lastMessage.is_user) { const responseText = lastMessage.mes; @@ -243,7 +249,7 @@ export async function onMessageReceived(data) { } } - // Trigger auto-update if enabled + // Trigger auto-update if enabled (for both separate and external modes) if (extensionSettings.autoUpdate) { setTimeout(async () => { await updateRPGData(renderUserStats, renderInfoBox, renderThoughts, renderInventory); @@ -313,12 +319,12 @@ export function onMessageSwiped(messageIndex) { return; } - console.log('[RPG Companion] ๐Ÿ”ต EVENT: onMessageSwiped at index:', messageIndex); + // console.log('[RPG Companion] ๐Ÿ”ต EVENT: onMessageSwiped at index:', messageIndex); // Get the message that was swiped const message = chat[messageIndex]; if (!message || message.is_user) { - console.log('[RPG Companion] ๐Ÿ”ต Ignoring swipe - message is user or undefined'); + // console.log('[RPG Companion] ๐Ÿ”ต Ignoring swipe - message is user or undefined'); return; } @@ -334,10 +340,10 @@ export function onMessageSwiped(messageIndex) { if (!isExistingSwipe) { // This is a NEW swipe that will trigger generation setLastActionWasSwipe(true); - console.log('[RPG Companion] ๐Ÿ”ต NEW swipe detected - Set lastActionWasSwipe = true'); + // console.log('[RPG Companion] ๐Ÿ”ต NEW swipe detected - Set lastActionWasSwipe = true'); } else { // This is navigating to an EXISTING swipe - don't change the flag - console.log('[RPG Companion] ๐Ÿ”ต EXISTING swipe navigation - lastActionWasSwipe unchanged =', lastActionWasSwipe); + // console.log('[RPG Companion] ๐Ÿ”ต EXISTING swipe navigation - lastActionWasSwipe unchanged =', lastActionWasSwipe); } // console.log('[RPG Companion] Loading data for swipe', currentSwipeId); @@ -358,9 +364,9 @@ export function onMessageSwiped(messageIndex) { parseUserStats(swipeData.userStats); } - console.log('[RPG Companion] ๐Ÿ”„ Loaded swipe data into lastGeneratedData for display:', currentSwipeId); + // console.log('[RPG Companion] ๐Ÿ”„ Loaded swipe data into lastGeneratedData for display:', currentSwipeId); } else { - console.log('[RPG Companion] โ„น๏ธ No stored data for swipe:', currentSwipeId); + // console.log('[RPG Companion] โ„น๏ธ No stored data for swipe:', currentSwipeId); } // Re-render the panels @@ -428,7 +434,7 @@ export function clearExtensionPrompts() { * Re-applies checkpoint if SillyTavern unhid messages */ export async function onGenerationEnded() { - console.log('[RPG Companion] ๐Ÿ onGenerationEnded called'); + // console.log('[RPG Companion] ๐Ÿ onGenerationEnded called'); // Note: isGenerating flag is cleared in onMessageReceived after parsing (together mode) // or in apiClient.js after separate generation completes (separate mode) diff --git a/src/systems/rendering/infoBox.js b/src/systems/rendering/infoBox.js index ed3c8fd..0538068 100644 --- a/src/systems/rendering/infoBox.js +++ b/src/systems/rendering/infoBox.js @@ -75,23 +75,23 @@ function separateEmojiFromText(str) { * Includes event listeners for editable fields. */ export function renderInfoBox() { - console.log('[RPG InfoBox Render] ==================== RENDERING INFO BOX ===================='); - console.log('[RPG InfoBox Render] showInfoBox setting:', extensionSettings.showInfoBox); - console.log('[RPG InfoBox Render] Container exists:', !!$infoBoxContainer); + // console.log('[RPG InfoBox Render] ==================== RENDERING INFO BOX ===================='); + // console.log('[RPG InfoBox Render] showInfoBox setting:', extensionSettings.showInfoBox); + // console.log('[RPG InfoBox Render] Container exists:', !!$infoBoxContainer); if (!extensionSettings.showInfoBox || !$infoBoxContainer) { - console.log('[RPG InfoBox Render] Exiting: showInfoBox or container is false'); + // console.log('[RPG InfoBox Render] Exiting: showInfoBox or container is false'); return; } // Use committedTrackerData as fallback if lastGeneratedData is empty (e.g., after page refresh) const infoBoxData = lastGeneratedData.infoBox || committedTrackerData.infoBox; - console.log('[RPG InfoBox Render] infoBoxData length:', infoBoxData ? infoBoxData.length : 'null'); - console.log('[RPG InfoBox Render] infoBoxData preview:', infoBoxData ? infoBoxData.substring(0, 200) : 'null'); + // console.log('[RPG InfoBox Render] infoBoxData length:', infoBoxData ? infoBoxData.length : 'null'); + // console.log('[RPG InfoBox Render] infoBoxData preview:', infoBoxData ? infoBoxData.substring(0, 200) : 'null'); // If no data yet, hide the container (e.g., after cache clear) if (!infoBoxData) { - console.log('[RPG InfoBox Render] No data, hiding container'); + // console.log('[RPG InfoBox Render] No data, hiding container'); $infoBoxContainer.empty().hide(); return; } @@ -574,6 +574,19 @@ export function renderInfoBox() { $infoBoxContainer.html(html); + // Add dynamic text scaling for location field + const updateLocationTextSize = ($element) => { + const text = $element.text(); + const charCount = text.length; + $element.css('--char-count', Math.min(charCount, 100)); + }; + + // Initial size update for location + const $locationText = $infoBoxContainer.find('[data-field="location"]'); + if ($locationText.length) { + updateLocationTextSize($locationText); + } + // Add event handlers for editable Info Box fields $infoBoxContainer.find('.rpg-editable').on('blur', function() { const $this = $(this); @@ -591,6 +604,11 @@ export function renderInfoBox() { } } + // Update location text size dynamically + if (field === 'location') { + updateLocationTextSize($this); + } + // Handle recent events separately if (field === 'event1' || field === 'event2' || field === 'event3') { updateRecentEvent(field, value); @@ -599,6 +617,11 @@ export function renderInfoBox() { } }); + // Update location size on input as well (real-time) + $infoBoxContainer.find('[data-field="location"]').on('input', function() { + updateLocationTextSize($(this)); + }); + // For date fields, show full value on focus $infoBoxContainer.find('[data-field="month"], [data-field="weekday"], [data-field="year"]').on('focus', function() { const fullValue = $(this).data('full-value'); @@ -707,7 +730,7 @@ export function updateInfoBoxField(field, value) { committedTrackerData.infoBox = lastGeneratedData.infoBox; saveChatData(); renderInfoBox(); - console.log('[RPG Companion] Updated info box field (v3 JSON):', { field, value }); + // console.log('[RPG Companion] Updated info box field (v3 JSON):', { field, value }); return; } } @@ -1061,6 +1084,6 @@ function updateRecentEvent(field, value) { window.RPGCompanion.updateWeatherEffect(); } - console.log(`[RPG Companion] Updated recent event ${field}:`, value); + // console.log(`[RPG Companion] Updated recent event ${field}:`, value); } } diff --git a/src/systems/rendering/musicPlayer.js b/src/systems/rendering/musicPlayer.js index b24e791..ba20aad 100644 --- a/src/systems/rendering/musicPlayer.js +++ b/src/systems/rendering/musicPlayer.js @@ -100,7 +100,7 @@ export function renderMusicPlayer(container) { // Find the chat form container and insert widget before (above) it const $chatForm = $('#send_form'); - console.log('[RPG Companion] Music Player: Found #send_form:', $chatForm.length > 0); + // console.log('[RPG Companion] Music Player: Found #send_form:', $chatForm.length > 0); if ($chatForm.length === 0) { console.error('[RPG Companion] Music Player: Could not find #send_form - cannot render widget!'); @@ -108,17 +108,17 @@ export function renderMusicPlayer(container) { } // Insert widget inside (at top of) the chat form - console.log('[RPG Companion] Music Player: Prepending widget to #send_form'); + // console.log('[RPG Companion] Music Player: Prepending widget to #send_form'); $chatForm.prepend(musicPlayerHtml); - console.log('[RPG Companion] Music Player: Widget inserted, checking if visible...'); + // console.log('[RPG Companion] Music Player: Widget inserted, checking if visible...'); const $widget = $('#rpg-chat-music-player'); - console.log('[RPG Companion] Music Player: Widget exists:', $widget.length > 0); + // console.log('[RPG Companion] Music Player: Widget exists:', $widget.length > 0); if ($widget.length > 0) { - console.log('[RPG Companion] Music Player: Widget position:', $widget.offset()); - console.log('[RPG Companion] Music Player: Widget dimensions:', { width: $widget.width(), height: $widget.height() }); - console.log('[RPG Companion] Music Player: Widget CSS display:', $widget.css('display')); - console.log('[RPG Companion] Music Player: Widget CSS visibility:', $widget.css('visibility')); + // console.log('[RPG Companion] Music Player: Widget position:', $widget.offset()); + // console.log('[RPG Companion] Music Player: Widget dimensions:', { width: $widget.width(), height: $widget.height() }); + // console.log('[RPG Companion] Music Player: Widget CSS display:', $widget.css('display')); + // console.log('[RPG Companion] Music Player: Widget CSS visibility:', $widget.css('visibility')); } // Bind play button click diff --git a/src/systems/rendering/thoughts.js b/src/systems/rendering/thoughts.js index 839412d..a808acf 100644 --- a/src/systems/rendering/thoughts.js +++ b/src/systems/rendering/thoughts.js @@ -39,7 +39,7 @@ function getLockIconHtml(tracker, path) { * Helper to log to both console and debug logs array */ function debugLog(message, data = null) { - console.log(message, data || ''); + // console.log(message, data || ''); if (extensionSettings.debugMode) { addDebugLog(message, data); } @@ -592,7 +592,7 @@ export function renderThoughts() { const character = $(this).data('character'); const field = $(this).data('field'); const value = $(this).text().trim(); - console.log('[RPG Companion] Character stat edit:', { character, field, value }); + // console.log('[RPG Companion] Character stat edit:', { character, field, value }); updateCharacterField(character, field, value); }); @@ -723,7 +723,7 @@ export function updateCharacterField(characterName, field, value) { else if (isThoughtsField && line.startsWith(thoughtsFieldName + ':')) { // Update thoughts field lines[i] = `${thoughtsFieldName}: ${value}`; - console.log('[RPG Companion] Updated thoughts:', lines[i]); + // console.log('[RPG Companion] Updated thoughts:', lines[i]); } } @@ -737,7 +737,7 @@ export function updateCharacterField(characterName, field, value) { } numValue = Math.max(0, Math.min(100, numValue)); - console.log('[RPG Companion] Updating stat:', { field, rawValue: value, cleanValue, numValue }); + // console.log('[RPG Companion] Updating stat:', { field, rawValue: value, cleanValue, numValue }); if (statsLineExists) { // Update existing Stats line @@ -750,7 +750,7 @@ export function updateCharacterField(characterName, field, value) { if (statParts[j].startsWith(field + ':')) { statParts[j] = `${field}: ${numValue}%`; statFound = true; - console.log('[RPG Companion] Updated stat part:', statParts[j]); + // console.log('[RPG Companion] Updated stat part:', statParts[j]); break; } } @@ -758,11 +758,11 @@ export function updateCharacterField(characterName, field, value) { // If stat wasn't found in existing parts, add it if (!statFound) { statParts.push(`${field}: ${numValue}%`); - console.log('[RPG Companion] Added new stat to existing line:', `${field}: ${numValue}%`); + // console.log('[RPG Companion] Added new stat to existing line:', `${field}: ${numValue}%`); } lines[statsLineIndex] = `Stats: ${statParts.join(' | ')}`; - console.log('[RPG Companion] Updated stats line:', lines[statsLineIndex]); + // console.log('[RPG Companion] Updated stats line:', lines[statsLineIndex]); } else { // Create new Stats line with all enabled stats (defaulting to 0% except the one being edited) const statsParts = enabledCharStats.map(s => { @@ -785,7 +785,7 @@ export function updateCharacterField(characterName, field, value) { } lines.splice(insertIndex, 0, newStatsLine); - console.log('[RPG Companion] Created new stats line:', newStatsLine); + // console.log('[RPG Companion] Created new stats line:', newStatsLine); characterEndIndex++; // Adjust end index since we inserted a line } } @@ -831,7 +831,7 @@ export function updateCharacterField(characterName, field, value) { lastGeneratedData.characterThoughts = lines.join('\n'); committedTrackerData.characterThoughts = lines.join('\n'); - console.log('[RPG Companion] Updated characterThoughts data:', lastGeneratedData.characterThoughts); + // console.log('[RPG Companion] Updated characterThoughts data:', lastGeneratedData.characterThoughts); const chat = getContext().chat; if (chat && chat.length > 0) { @@ -1075,12 +1075,12 @@ function initThoughtIconDragHandlers() { if (thoughtIconDragHandlersInitialized) return; thoughtIconDragHandlersInitialized = true; - console.log('[Thought Icon] Initializing drag handlers ONCE - will attach to icon when created'); + // console.log('[Thought Icon] Initializing drag handlers ONCE - will attach to icon when created'); } // Function to attach drag handlers to a specific icon element function attachDragHandlersToIcon($icon) { - console.log('[Thought Icon] Attaching handlers to icon element'); + // console.log('[Thought Icon] Attaching handlers to icon element'); // Remove any existing handlers $icon.off('.thoughtIconDrag'); @@ -1089,20 +1089,20 @@ function attachDragHandlersToIcon($icon) { $icon.on('click.thoughtIconDrag', function(e) { // Check global flag set immediately after drag completes if (justFinishedDragging) { - console.log('[Thought Icon] CLICK blocked - just finished dragging'); + // console.log('[Thought Icon] CLICK blocked - just finished dragging'); e.preventDefault(); e.stopPropagation(); e.stopImmediatePropagation(); return false; } - console.log('[Thought Icon] CLICK detected on icon!'); + // console.log('[Thought Icon] CLICK detected on icon!'); }); // Touch drag support - mobile only $icon.on('touchstart.thoughtIconDrag', function(e) { if (window.innerWidth > 1000) return; - console.log('[Thought Icon] touchstart'); + // console.log('[Thought Icon] touchstart'); touchMoved = false; dragStartTime = Date.now(); const touch = e.originalEvent.touches[0]; @@ -1120,7 +1120,7 @@ function attachDragHandlersToIcon($icon) { if (window.innerWidth > 1000) return; if (!touchMoved) { - console.log('[Thought Icon] touchmove - first movement'); + // console.log('[Thought Icon] touchmove - first movement'); } touchMoved = true; const touch = e.originalEvent.touches[0]; @@ -1160,7 +1160,7 @@ function attachDragHandlersToIcon($icon) { }); $icon.on('touchend.thoughtIconDrag', function(e) { - console.log('[Thought Icon] touchend - isDragging:', isDragging, 'touchMoved:', touchMoved); + // console.log('[Thought Icon] touchend - isDragging:', isDragging, 'touchMoved:', touchMoved); if (isDragging) { const offset = $(this).offset(); @@ -1193,7 +1193,7 @@ function attachDragHandlersToIcon($icon) { e.preventDefault(); e.stopPropagation(); } else if (!touchMoved) { - console.log('[Thought Icon] Opening panel - was a tap'); + // console.log('[Thought Icon] Opening panel - was a tap'); const $panel = $('#rpg-thought-panel'); const iconOffset = $(this).offset(); if (iconOffset) { @@ -1207,7 +1207,7 @@ function attachDragHandlersToIcon($icon) { $(this).addClass('rpg-hidden'); $panel.fadeIn(200); } else { - console.log('[Thought Icon] Did nothing - touchMoved but not isDragging'); + // console.log('[Thought Icon] Did nothing - touchMoved but not isDragging'); } }); @@ -1217,7 +1217,7 @@ function attachDragHandlersToIcon($icon) { $icon.on('mousedown.thoughtIconDrag', function(e) { if (window.innerWidth > 1000) return; - console.log('[Thought Icon] mousedown'); + // console.log('[Thought Icon] mousedown'); e.preventDefault(); mouseDown = true; @@ -1237,7 +1237,7 @@ function attachDragHandlersToIcon($icon) { if (!mouseDown || window.innerWidth > 1000) return; if (!touchMoved) { - console.log('[Thought Icon] mousemove - first movement'); + // console.log('[Thought Icon] mousemove - first movement'); } touchMoved = true; @@ -1280,7 +1280,7 @@ function attachDragHandlersToIcon($icon) { $(document).on('mouseup.thoughtIconDrag', function(e) { if (!mouseDown) return; - console.log('[Thought Icon] mouseup - isDragging:', isDragging, 'touchMoved:', touchMoved); + // console.log('[Thought Icon] mouseup - isDragging:', isDragging, 'touchMoved:', touchMoved); mouseDown = false; @@ -1568,22 +1568,82 @@ export function createThoughtPanel($message, thoughtsArray) { // Load saved icon position in mobile, or default to center of viewport if (extensionSettings.thoughtIconPosition && extensionSettings.thoughtIconPosition.top && extensionSettings.thoughtIconPosition.left) { const pos = extensionSettings.thoughtIconPosition; - $thoughtIcon.css({ - top: pos.top, - left: pos.left, - transform: 'none', - right: 'auto', - bottom: 'auto' - }); + + // Validate saved position - check if it's not at the very top (likely invalid) + const savedTop = parseInt(pos.top); + const topBar = $('#top-settings-holder'); + const topBarHeight = topBar.length ? topBar.outerHeight() : 60; + + // If saved position is above or too close to top bar, recalculate default + if (savedTop < topBarHeight + 50) { + // console.log('[Thought Icon] Saved position invalid (too close to top), recalculating default'); + // Clear invalid saved position + delete extensionSettings.thoughtIconPosition; + saveSettings(); + + // Calculate new default position + setTimeout(() => { + const viewportHeight = window.innerHeight; + const viewportWidth = window.innerWidth; + + const defaultTop = topBarHeight + ((viewportHeight - topBarHeight) / 2) - 22; + const defaultLeft = (viewportWidth * 0.75) - 22; + + // console.log('[Thought Icon] Setting new default position:', { + // topBarHeight, + // viewportHeight, + // viewportWidth, + // calculatedTop: defaultTop, + // calculatedLeft: defaultLeft + // }); + + $thoughtIcon.css({ + top: `${defaultTop}px`, + left: `${defaultLeft}px`, + transform: 'none', + right: 'auto', + bottom: 'auto' + }); + }, 100); + } else { + // Position is valid, use it + $thoughtIcon.css({ + top: pos.top, + left: pos.left, + transform: 'none', + right: 'auto', + bottom: 'auto' + }); + } } else { - // Default position: center of viewport - $thoughtIcon.css({ - top: '50%', - left: '50%', - transform: 'translate(-50%, -50%)', - right: 'auto', - bottom: 'auto' - }); + // Default position: center-right of viewport, accounting for top bar + // Use setTimeout to ensure DOM is fully rendered before calculating positions + setTimeout(() => { + const topBar = $('#top-settings-holder'); + const topBarHeight = topBar.length ? topBar.outerHeight() : 60; + const viewportHeight = window.innerHeight; + const viewportWidth = window.innerWidth; + + // Position in the center vertically (accounting for top bar) and slightly right + const defaultTop = topBarHeight + ((viewportHeight - topBarHeight) / 2) - 22; // 22 = half of icon height + const defaultLeft = (viewportWidth * 0.75) - 22; // 75% from left, minus half icon width + + // console.log('[Thought Icon] Setting default position:', { + // topBarHeight, + // viewportHeight, + // viewportWidth, + // calculatedTop: defaultTop, + // calculatedLeft: defaultLeft + // }); + + $thoughtIcon.css({ + top: `${defaultTop}px`, + left: `${defaultLeft}px`, + transform: 'none', + right: 'auto', + bottom: 'auto' + }); + }, 100); } } else { // Desktop: show panel, hide icon with class diff --git a/src/systems/rendering/userStats.js b/src/systems/rendering/userStats.js index 4d4fc73..a85069e 100644 --- a/src/systems/rendering/userStats.js +++ b/src/systems/rendering/userStats.js @@ -181,12 +181,12 @@ export function renderUserStats() { // Don't render if no data exists (e.g., after cache clear) // Check both lastGeneratedData and committedTrackerData - console.log('[RPG UserStats Render] Checking data:', { - hasLastGenerated: !!lastGeneratedData.userStats, - hasCommitted: !!committedTrackerData.userStats, - lastGeneratedPreview: lastGeneratedData.userStats ? lastGeneratedData.userStats.substring(0, 100) : 'null', - committedPreview: committedTrackerData.userStats ? committedTrackerData.userStats.substring(0, 100) : 'null' - }); + // console.log('[RPG UserStats Render] Checking data:', { + // hasLastGenerated: !!lastGeneratedData.userStats, + // hasCommitted: !!committedTrackerData.userStats, + // lastGeneratedPreview: lastGeneratedData.userStats ? lastGeneratedData.userStats.substring(0, 100) : 'null', + // committedPreview: committedTrackerData.userStats ? committedTrackerData.userStats.substring(0, 100) : 'null' + // }); if (!lastGeneratedData.userStats && !committedTrackerData.userStats) { // Always render to the #rpg-user-stats container (mobile layout just moves it around in DOM) @@ -200,15 +200,15 @@ export function renderUserStats() { } const stats = extensionSettings.userStats; - console.log('[RPG UserStats Render] Current extensionSettings.userStats:', { - health: stats.health, - satiety: stats.satiety, - energy: stats.energy, - hygiene: stats.hygiene, - arousal: stats.arousal, - mood: stats.mood, - conditions: stats.conditions - }); + // console.log('[RPG UserStats Render] Current extensionSettings.userStats:', { + // health: stats.health, + // satiety: stats.satiety, + // energy: stats.energy, + // hygiene: stats.hygiene, + // arousal: stats.arousal, + // mood: stats.mood, + // conditions: stats.conditions + // }); const config = extensionSettings.trackerConfig?.userStats || { customStats: [ { id: 'health', name: 'Health', enabled: true }, @@ -394,13 +394,13 @@ export function renderUserStats() { html += ''; // Close rpg-stats-content - console.log('[RPG UserStats Render] Generated HTML length:', html.length); - console.log('[RPG UserStats Render] HTML preview:', html.substring(0, 300)); - console.log('[RPG UserStats Render] Container exists:', !!$userStatsContainer, '$userStatsContainer length:', $userStatsContainer?.length); + // console.log('[RPG UserStats Render] Generated HTML length:', html.length); + // console.log('[RPG UserStats Render] HTML preview:', html.substring(0, 300)); + // console.log('[RPG UserStats Render] Container exists:', !!$userStatsContainer, '$userStatsContainer length:', $userStatsContainer?.length); // Always render to the #rpg-user-stats container (mobile layout just moves it around in DOM) $userStatsContainer.html(html); - console.log('[RPG UserStats Render] โœ“ HTML rendered to #rpg-user-stats container'); + // console.log('[RPG UserStats Render] โœ“ HTML rendered to #rpg-user-stats container'); // Add event listeners for editable stat values $('.rpg-editable-stat').on('blur', function() { diff --git a/src/systems/ui/encounterUI.js b/src/systems/ui/encounterUI.js index 8a52435..aa6c055 100644 --- a/src/systems/ui/encounterUI.js +++ b/src/systems/ui/encounterUI.js @@ -1001,7 +1001,7 @@ export class EncounterModal { { clearChatInput: false } ); - console.log(`[RPG Companion] Added combat summary to chat as "${speakerName}"`); + // console.log(`[RPG Companion] Added combat summary to chat as "${speakerName}"`); // Update combat over screen this.updateCombatOverScreen(true, speakerName); @@ -1259,7 +1259,7 @@ export class EncounterModal { return; } - console.log('[RPG Companion] Regenerating request:', this.lastRequest.type); + // console.log('[RPG Companion] Regenerating request:', this.lastRequest.type); if (this.lastRequest.type === 'init') { // Retry initialization @@ -1327,7 +1327,7 @@ export class EncounterModal { return; } - console.log('[RPG Companion] Regenerating request:', this.lastRequest.type); + // console.log('[RPG Companion] Regenerating request:', this.lastRequest.type); if (this.lastRequest.type === 'init') { // Retry initialization @@ -1369,7 +1369,7 @@ export class EncounterModal { this.modal.setAttribute('data-weather', weather.toLowerCase()); } - console.log('[RPG Companion] Applied environment styling:', styleNotes); + // console.log('[RPG Companion] Applied environment styling:', styleNotes); } /** diff --git a/src/systems/ui/layout.js b/src/systems/ui/layout.js index 79fc813..5e2f827 100644 --- a/src/systems/ui/layout.js +++ b/src/systems/ui/layout.js @@ -92,12 +92,12 @@ export function updateCollapseToggleIcon() { const isOpen = $panel.hasClass('rpg-mobile-open'); const isLeftPanel = $panel.hasClass('rpg-position-left'); - console.log('[RPG Mobile] updateCollapseToggleIcon:', { - isMobile: true, - isOpen, - isLeftPanel, - settingIcon: isOpen ? (isLeftPanel ? 'chevron-left' : 'chevron-right') : (isLeftPanel ? 'chevron-right' : 'chevron-left') - }); + // console.log('[RPG Mobile] updateCollapseToggleIcon:', { + // isMobile: true, + // isOpen, + // isLeftPanel, + // settingIcon: isOpen ? (isLeftPanel ? 'chevron-left' : 'chevron-right') : (isLeftPanel ? 'chevron-right' : 'chevron-left') + // }); if (isLeftPanel) { if (isOpen) { @@ -157,44 +157,44 @@ export function setupCollapseToggle() { // On mobile: button toggles panel open/closed (same as desktop behavior) if (isMobile) { const isOpen = $panel.hasClass('rpg-mobile-open'); - console.log('[RPG Mobile] Collapse toggle clicked. Current state:', { - isOpen, - panelClasses: $panel.attr('class'), - inlineStyles: $panel.attr('style'), - panelPosition: { - top: $panel.css('top'), - bottom: $panel.css('bottom'), - transform: $panel.css('transform'), - visibility: $panel.css('visibility') - } - }); + // console.log('[RPG Mobile] Collapse toggle clicked. Current state:', { + // isOpen, + // panelClasses: $panel.attr('class'), + // inlineStyles: $panel.attr('style'), + // panelPosition: { + // top: $panel.css('top'), + // bottom: $panel.css('bottom'), + // transform: $panel.css('transform'), + // visibility: $panel.css('visibility') + // } + // }); if (isOpen) { // Close panel with animation - console.log('[RPG Mobile] Closing panel'); + // console.log('[RPG Mobile] Closing panel'); closeMobilePanelWithAnimation(); } else { // Open panel - console.log('[RPG Mobile] Opening panel'); + // console.log('[RPG Mobile] Opening panel'); $panel.addClass('rpg-mobile-open'); const $overlay = $('
'); $('body').append($overlay); // Debug: Check state after animation should complete setTimeout(() => { - console.log('[RPG Mobile] 500ms after opening:', { - panelClasses: $panel.attr('class'), - hasOpenClass: $panel.hasClass('rpg-mobile-open'), - visibility: $panel.css('visibility'), - transform: $panel.css('transform'), - display: $panel.css('display'), - opacity: $panel.css('opacity') - }); + // console.log('[RPG Mobile] 500ms after opening:', { + // panelClasses: $panel.attr('class'), + // hasOpenClass: $panel.hasClass('rpg-mobile-open'), + // visibility: $panel.css('visibility'), + // transform: $panel.css('transform'), + // display: $panel.css('display'), + // opacity: $panel.css('opacity') + // }); }, 500); // Close when clicking overlay $overlay.on('click', function() { - console.log('[RPG Mobile] Overlay clicked - closing panel'); + // console.log('[RPG Mobile] Overlay clicked - closing panel'); closeMobilePanelWithAnimation(); updateCollapseToggleIcon(); }); @@ -203,20 +203,20 @@ export function setupCollapseToggle() { // Update icon to reflect new state updateCollapseToggleIcon(); - console.log('[RPG Mobile] After toggle:', { - panelClasses: $panel.attr('class'), - inlineStyles: $panel.attr('style'), - panelPosition: { - top: $panel.css('top'), - bottom: $panel.css('bottom'), - transform: $panel.css('transform'), - visibility: $panel.css('visibility') - }, - gameContainer: { - opacity: $('.rpg-game-container').css('opacity'), - visibility: $('.rpg-game-container').css('visibility') - } - }); + // console.log('[RPG Mobile] After toggle:', { + // panelClasses: $panel.attr('class'), + // inlineStyles: $panel.attr('style'), + // panelPosition: { + // top: $panel.css('top'), + // bottom: $panel.css('bottom'), + // transform: $panel.css('transform'), + // visibility: $panel.css('visibility') + // }, + // gameContainer: { + // opacity: $('.rpg-game-container').css('opacity'), + // visibility: $('.rpg-game-container').css('visibility') + // } + // }); return; } diff --git a/src/systems/ui/mobile.js b/src/systems/ui/mobile.js index 805298d..9426140 100644 --- a/src/systems/ui/mobile.js +++ b/src/systems/ui/mobile.js @@ -55,13 +55,13 @@ export function setupMobileToggle() { const $overlay = $('
'); // DIAGNOSTIC: Check if elements exist and log setup state - console.log('[RPG Mobile] ========================================'); - console.log('[RPG Mobile] setupMobileToggle called'); - console.log('[RPG Mobile] Button exists:', $mobileToggle.length > 0, 'jQuery object:', $mobileToggle); - console.log('[RPG Mobile] Panel exists:', $panel.length > 0); - console.log('[RPG Mobile] Window width:', window.innerWidth); - console.log('[RPG Mobile] Is mobile viewport (<=1000):', window.innerWidth <= 1000); - console.log('[RPG Mobile] ========================================'); + // console.log('[RPG Mobile] ========================================'); + // console.log('[RPG Mobile] setupMobileToggle called'); + // console.log('[RPG Mobile] Button exists:', $mobileToggle.length > 0, 'jQuery object:', $mobileToggle); + // console.log('[RPG Mobile] Panel exists:', $panel.length > 0); + // console.log('[RPG Mobile] Window width:', window.innerWidth); + // console.log('[RPG Mobile] Is mobile viewport (<=1000):', window.innerWidth <= 1000); + // console.log('[RPG Mobile] ========================================'); if ($mobileToggle.length === 0) { console.error('[RPG Mobile] ERROR: Mobile toggle button not found in DOM!'); @@ -72,7 +72,7 @@ export function setupMobileToggle() { // Load and apply saved FAB position if (extensionSettings.mobileFabPosition) { const pos = extensionSettings.mobileFabPosition; - console.log('[RPG Mobile] Loading saved FAB position:', pos); + // console.log('[RPG Mobile] Loading saved FAB position:', pos); // Apply saved position if (pos.top) $mobileToggle.css('top', pos.top); @@ -250,7 +250,7 @@ export function setupMobileToggle() { extensionSettings.mobileFabPosition = newPosition; saveSettings(); - console.log('[RPG Mobile] Saved new FAB position (mouse):', newPosition); + // console.log('[RPG Mobile] Saved new FAB position (mouse):', newPosition); // Constrain to viewport bounds (now that position is saved) setTimeout(() => constrainFabToViewport(), 10); @@ -291,7 +291,7 @@ export function setupMobileToggle() { extensionSettings.mobileFabPosition = newPosition; saveSettings(); - console.log('[RPG Mobile] Saved new FAB position:', newPosition); + // console.log('[RPG Mobile] Saved new FAB position:', newPosition); // Constrain to viewport bounds (now that position is saved) setTimeout(() => constrainFabToViewport(), 10); @@ -304,7 +304,7 @@ export function setupMobileToggle() { isDragging = false; } else { // Was a tap - toggle panel - console.log('[RPG Mobile] Quick tap detected - toggling panel'); + // console.log('[RPG Mobile] Quick tap detected - toggling panel'); if ($panel.hasClass('rpg-mobile-open')) { // Close panel with animation @@ -327,28 +327,28 @@ export function setupMobileToggle() { $mobileToggle.on('click', function(e) { // Skip if we just finished dragging if ($mobileToggle.data('just-dragged')) { - console.log('[RPG Mobile] Click blocked - just finished dragging'); + // console.log('[RPG Mobile] Click blocked - just finished dragging'); return; } - console.log('[RPG Mobile] >>> CLICK EVENT FIRED <<<', { - windowWidth: window.innerWidth, - isMobileViewport: window.innerWidth <= 1000, - panelOpen: $panel.hasClass('rpg-mobile-open') - }); + // console.log('[RPG Mobile] >>> CLICK EVENT FIRED <<<', { + // windowWidth: window.innerWidth, + // isMobileViewport: window.innerWidth <= 1000, + // panelOpen: $panel.hasClass('rpg-mobile-open') + // }); // Work on both mobile and desktop (removed viewport check) if ($panel.hasClass('rpg-mobile-open')) { - console.log('[RPG Mobile] Click: Closing panel'); + // console.log('[RPG Mobile] Click: Closing panel'); closeMobilePanelWithAnimation(); } else { - console.log('[RPG Mobile] Click: Opening panel'); + // console.log('[RPG Mobile] Click: Opening panel'); $panel.addClass('rpg-mobile-open'); $('body').append($overlay); $mobileToggle.addClass('active'); $overlay.on('click', function() { - console.log('[RPG Mobile] Overlay clicked - closing panel'); + // console.log('[RPG Mobile] Overlay clicked - closing panel'); closeMobilePanelWithAnimation(); }); } @@ -367,7 +367,7 @@ export function setupMobileToggle() { // Transitioning from desktop to mobile - handle immediately for smooth transition if (!wasMobile && isMobile) { - console.log('[RPG Mobile] Transitioning desktop -> mobile'); + // console.log('[RPG Mobile] Transitioning desktop -> mobile'); // Show mobile toggle button $mobileToggle.show(); @@ -391,16 +391,16 @@ export function setupMobileToggle() { // Clear any inline styles that might be overriding CSS $panel.attr('style', ''); - console.log('[RPG Mobile] After cleanup:', { - panelClasses: $panel.attr('class'), - inlineStyles: $panel.attr('style'), - panelPosition: { - top: $panel.css('top'), - bottom: $panel.css('bottom'), - transform: $panel.css('transform'), - visibility: $panel.css('visibility') - } - }); + // console.log('[RPG Mobile] After cleanup:', { + // panelClasses: $panel.attr('class'), + // inlineStyles: $panel.attr('style'), + // panelPosition: { + // top: $panel.css('top'), + // bottom: $panel.css('bottom'), + // transform: $panel.css('transform'), + // visibility: $panel.css('visibility') + // } + // }); // Set up mobile tabs IMMEDIATELY (no debounce delay) setupMobileTabs(); @@ -462,17 +462,14 @@ export function setupMobileToggle() { // Clear any inline styles $panel.attr('style', ''); - console.log('[RPG Mobile] Initial load on mobile viewport:', { - panelClasses: $panel.attr('class'), - inlineStyles: $panel.attr('style'), - panelPosition: { - top: $panel.css('top'), - bottom: $panel.css('top'), - transform: $panel.css('transform'), - visibility: $panel.css('visibility') - } - }); - setupMobileTabs(); + // console.log('[RPG Mobile] Initial load on mobile viewport:', { + // panelClasses: $panel.attr('class'), + // inlineStyles: $panel.attr('style'), + // panelPosition: { + // top: $panel.css('top'), + // bottom: $panel.css('top'), + // transform: $panel.css('transform'), + // visibility: $panel.css('visibility')\n // }\n // });\n setupMobileTabs(); // Set initial icon for mobile updateCollapseToggleIcon(); // Show mobile toggle on mobile viewport @@ -491,7 +488,7 @@ export function setupMobileToggle() { export function constrainFabToViewport() { // Only constrain if user has set a custom position if (!extensionSettings.mobileFabPosition) { - console.log('[RPG Mobile] Skipping viewport constraint - using CSS defaults'); + // console.log('[RPG Mobile] Skipping viewport constraint - using CSS defaults'); return; } @@ -500,7 +497,7 @@ export function constrainFabToViewport() { // Skip if button is not visible if (!$mobileToggle.is(':visible')) { - console.log('[RPG Mobile] Skipping viewport constraint - button not visible'); + // console.log('[RPG Mobile] Skipping viewport constraint - button not visible'); return; } @@ -530,12 +527,12 @@ export function constrainFabToViewport() { // Only update if position changed if (newX !== currentX || newY !== currentY) { - console.log('[RPG Mobile] Constraining FAB to viewport:', { - old: { x: currentX, y: currentY }, - new: { x: newX, y: newY }, - viewport: { width: window.innerWidth, height: window.innerHeight }, - topBarHeight - }); + // console.log('[RPG Mobile] Constraining FAB to viewport:', { + // old: { x: currentX, y: currentY }, + // new: { x: newX, y: newY }, + // viewport: { width: window.innerWidth, height: window.innerHeight }, + // topBarHeight + // }); // Apply new position $mobileToggle.css({ @@ -816,12 +813,12 @@ export function setupRefreshButtonDrag() { return; } - console.log('[RPG Mobile] setupRefreshButtonDrag called'); + // console.log('[RPG Mobile] setupRefreshButtonDrag called'); // Load and apply saved position if (extensionSettings.mobileRefreshPosition) { const pos = extensionSettings.mobileRefreshPosition; - console.log('[RPG Mobile] Loading saved refresh button position:', pos); + // console.log('[RPG Mobile] Loading saved refresh button position:', pos); // Apply saved position if (pos.top) $refreshBtn.css('top', pos.top); @@ -1031,12 +1028,12 @@ export function setupDebugButtonDrag() { return; } - console.log('[RPG Mobile] setupDebugButtonDrag called'); + // console.log('[RPG Mobile] setupDebugButtonDrag called'); // Load and apply saved position if (extensionSettings.debugFabPosition) { const pos = extensionSettings.debugFabPosition; - console.log('[RPG Mobile] Loading saved debug button position:', pos); + // console.log('[RPG Mobile] Loading saved debug button position:', pos); // Apply saved position if (pos.top) $debugBtn.css('top', pos.top); diff --git a/src/systems/ui/modals.js b/src/systems/ui/modals.js index 8602d4f..ae051bc 100644 --- a/src/systems/ui/modals.js +++ b/src/systems/ui/modals.js @@ -355,7 +355,7 @@ export function setupSettingsPopup() { // Clear cache button $('#rpg-clear-cache').on('click', function() { - console.log('[RPG Companion] Clear Cache button clicked'); + // console.log('[RPG Companion] Clear Cache button clicked'); // Clear the data (set to null so panels show "not generated yet") lastGeneratedData.userStats = null; @@ -375,7 +375,7 @@ export function setupSettingsPopup() { const context = getContext(); if (context.chat_metadata && context.chat_metadata.rpg_companion) { delete context.chat_metadata.rpg_companion; - console.log('[RPG Companion] Cleared chat_metadata.rpg_companion for current chat'); + // console.log('[RPG Companion] Cleared chat_metadata.rpg_companion for current chat'); } // Clear all message swipe data @@ -495,7 +495,7 @@ export function setupSettingsPopup() { renderInventory(); renderQuests(); - console.log('[RPG Companion] Cache cleared successfully'); + // console.log('[RPG Companion] Cache cleared successfully'); }); return settingsModal; diff --git a/src/systems/ui/trackerEditor.js b/src/systems/ui/trackerEditor.js index fa20b66..f51a47e 100644 --- a/src/systems/ui/trackerEditor.js +++ b/src/systems/ui/trackerEditor.js @@ -243,7 +243,7 @@ function exportTrackerPreset() { document.body.removeChild(link); URL.revokeObjectURL(url); - console.log('[RPG Companion] Tracker preset exported successfully'); + // console.log('[RPG Companion] Tracker preset exported successfully'); toastr.success(i18n.getTranslation('template.trackerEditorModal.messages.exportSuccess') || 'Tracker preset exported successfully!'); } catch (error) { console.error('[RPG Companion] Error exporting tracker preset:', error); @@ -292,7 +292,7 @@ function importTrackerPreset() { // Re-render the editor UI renderEditorUI(); - console.log('[RPG Companion] Tracker preset imported successfully'); + // console.log('[RPG Companion] Tracker preset imported successfully'); toastr.success(i18n.getTranslation('template.trackerEditorModal.messages.importSuccess') || 'Tracker preset imported successfully!'); } catch (error) { console.error('[RPG Companion] Error importing tracker preset:', error); diff --git a/src/utils/jsonMigration.js b/src/utils/jsonMigration.js index 90cbb9c..c122b84 100644 --- a/src/utils/jsonMigration.js +++ b/src/utils/jsonMigration.js @@ -357,7 +357,7 @@ export function migrateCharactersToJSON(textData) { * @returns {Promise} */ export async function migrateToV3JSON() { - console.log('[RPG Migration] Starting migration to v3 JSON format...'); + // console.log('[RPG Migration] Starting migration to v3 JSON format...'); const migrated = { userStats: null, @@ -367,28 +367,28 @@ export async function migrateToV3JSON() { // Migrate User Stats if (committedTrackerData.userStats && typeof committedTrackerData.userStats === 'string') { - console.log('[RPG Migration] Migrating User Stats...'); + // console.log('[RPG Migration] Migrating User Stats...'); migrated.userStats = migrateUserStatsToJSON(committedTrackerData.userStats); if (migrated.userStats) { - console.log('[RPG Migration] โœ“ User Stats migrated'); + // console.log('[RPG Migration] โœ“ User Stats migrated'); } } // Migrate Info Box if (committedTrackerData.infoBox && typeof committedTrackerData.infoBox === 'string') { - console.log('[RPG Migration] Migrating Info Box...'); + // console.log('[RPG Migration] Migrating Info Box...'); migrated.infoBox = migrateInfoBoxToJSON(committedTrackerData.infoBox); if (migrated.infoBox) { - console.log('[RPG Migration] โœ“ Info Box migrated'); + // console.log('[RPG Migration] โœ“ Info Box migrated'); } } // Migrate Present Characters if (committedTrackerData.characterThoughts && typeof committedTrackerData.characterThoughts === 'string') { - console.log('[RPG Migration] Migrating Present Characters...'); + // console.log('[RPG Migration] Migrating Present Characters...'); migrated.characterThoughts = migrateCharactersToJSON(committedTrackerData.characterThoughts); if (migrated.characterThoughts) { - console.log('[RPG Migration] โœ“ Present Characters migrated'); + // console.log('[RPG Migration] โœ“ Present Characters migrated'); } } @@ -397,7 +397,7 @@ export async function migrateToV3JSON() { // Initialize lockedItems if not present if (!extensionSettings.lockedItems) { - console.log('[RPG Migration] Initializing lockedItems structure...'); + // console.log('[RPG Migration] Initializing lockedItems structure...'); updateExtensionSettings({ lockedItems: { stats: [], @@ -429,5 +429,5 @@ export async function migrateToV3JSON() { await saveChatData(); await saveSettings(); - console.log('[RPG Migration] โœ… Migration to v3 JSON format complete'); + // console.log('[RPG Migration] โœ… Migration to v3 JSON format complete'); } diff --git a/src/utils/jsonRepair.js b/src/utils/jsonRepair.js index e5b5ff0..5d08599 100644 --- a/src/utils/jsonRepair.js +++ b/src/utils/jsonRepair.js @@ -81,7 +81,7 @@ export function repairJSON(jsonString) { const result = fn(); // Validate it's actually an object or array if (result && (typeof result === 'object')) { - console.log('[RPG JSON Repair] โœ“ Repaired using Function constructor'); + // console.log('[RPG JSON Repair] โœ“ Repaired using Function constructor'); return result; } } catch (e) { diff --git a/style.css b/style.css index 3e8f703..5513d28 100644 --- a/style.css +++ b/style.css @@ -1616,22 +1616,43 @@ body:has(.rpg-panel.rpg-position-left) #sheld { } .rpg-location-text { - font-size: clamp(0.625rem, 0.6vw, 0.75rem); font-weight: bold; color: var(--rpg-text); text-align: center; line-height: 1.2; - padding: 0; + padding: 0.25em 0.5em; margin: 0; word-wrap: break-word; overflow-wrap: break-word; hyphens: auto; flex: 1 1 auto; min-height: 0; - overflow: hidden; - display: -webkit-box; - -webkit-line-clamp: 2; - -webkit-box-orient: vertical; + max-height: 4em; + width: 100%; + display: block; + overflow-y: auto; + overflow-x: hidden; + /* Dynamic text scaling based on content length */ + font-size: clamp(0.45rem, calc(0.75rem - 0.005rem * var(--char-count, 0)), 0.75rem); +} + +/* Custom scrollbar for location text */ +.rpg-location-text::-webkit-scrollbar { + width: 4px; +} + +.rpg-location-text::-webkit-scrollbar-track { + background: rgba(0, 0, 0, 0.2); + border-radius: 2px; +} + +.rpg-location-text::-webkit-scrollbar-thumb { + background: var(--rpg-border); + border-radius: 2px; +} + +.rpg-location-text::-webkit-scrollbar-thumb:hover { + background: var(--rpg-highlight); } /* Row 3: Recent Events */ @@ -5122,9 +5143,13 @@ body:has(.rpg-panel.rpg-position-left) #sheld { left: auto !important; /* Mobile panel sizing */ + width: 85vw !important; width: 85dvw !important; max-width: 400px !important; + height: calc(100vh - var(--topBarBlockSize)) !important; height: calc(100dvh - var(--topBarBlockSize)) !important; + max-height: calc(100vh - var(--topBarBlockSize)) !important; + max-height: calc(100dvh - var(--topBarBlockSize)) !important; /* Hidden by default - completely removed from layout */ display: none !important; @@ -5143,12 +5168,18 @@ body:has(.rpg-panel.rpg-position-left) #sheld { /* Allow collapse button to show outside panel */ .rpg-game-container { overflow: visible !important; + height: 100% !important; + max-height: 100% !important; + box-sizing: border-box !important; + padding: 0.75em !important; } /* But keep content scrollable */ #rpg-panel-content { overflow-y: auto !important; overflow-x: hidden !important; + max-height: 100% !important; + height: 100% !important; } /* Show panel when opened with slide-in animation */ @@ -5317,10 +5348,12 @@ body:has(.rpg-panel.rpg-position-left) #sheld { display: flex; flex-direction: column; height: 100%; + max-height: 100%; min-height: 0; margin: -12px -12px 16px -12px; overflow-x: auto; overflow-y: hidden; + box-sizing: border-box; } /* Tab container at top of panel */ @@ -5501,7 +5534,11 @@ body:has(.rpg-panel.rpg-position-left) #sheld { } .rpg-location-text { - font-size: min(2.8vw, 0.875rem) !important; + /* Dynamic text scaling based on content length - mobile override */ + font-size: clamp(0.45rem, calc(0.875rem - 0.005rem * var(--char-count, 0)), 0.875rem) !important; + max-height: 4.5em !important; + overflow-y: auto !important; + overflow-x: hidden !important; } .rpg-map-marker { diff --git a/template.html b/template.html index 5081ea8..4d7b915 100644 --- a/template.html +++ b/template.html @@ -935,9 +935,14 @@
  • Fixed smaller bugs.
  • +

    Recommended Models:

    +

    + For the extension to work properly, **it is not recommended to use any models below 20B, especially if they're old.** It works best with the SOTA models such as Deepseek, Claude, GPT, or Gemini. +

    +

    Special thanks to all the other contributors for this project:

    - Paperboygold, Munimunigamer, Subarashimo, Lilminzyu, Claude (???), IDeathByte, Chungchandev, Joenunezb, and Amauragis! + Paperboygold, Munimunigamer, Subarashimo, Lilminzyu, Claude (???), IDeathByte, Chungchandev, Joenunezb, and Amauragis.