v3.1.0: Add parser error detection and recommended models section
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
+1
-1
@@ -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"
|
||||
}
|
||||
|
||||
+11
-2
@@ -29,17 +29,26 @@
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div style="margin-top: 15px; text-align: center; opacity: 0.7; font-size: 0.8em; line-height: 1.5;">
|
||||
<div style="margin-bottom: 5px;">
|
||||
<i class="fa-solid fa-microchip"></i> <strong data-i18n="settings.recommendedModels.title">Recommended Models:</strong>
|
||||
</div>
|
||||
<div style="opacity: 0.8; font-size: 0.9em;" data-i18n="settings.recommendedModels.description">
|
||||
For the extension to work properly, <strong>it is not recommended to use any models below 20B, especially if they're old.</strong> It works best with the SOTA models such as Deepseek, Claude, GPT, or Gemini.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="margin-top: 15px; text-align: center; opacity: 0.7; font-size: 0.8em; line-height: 1.5;">
|
||||
<div style="margin-bottom: 5px;">
|
||||
<i class="fa-solid fa-users"></i> <strong>Contributors:</strong>
|
||||
</div>
|
||||
<div style="opacity: 0.8; font-size: 0.9em;">
|
||||
SpicyMarinara, Paperboygold, Munimunigamer, Subarashimo, Lilminzyu, Claude, IDeathByte, Chungchandev, Joenunezb, and Amauragis
|
||||
SpicyMarinara, Paperboygold, Munimunigamer, Subarashimo, Lilminzyu, Claude, IDeathByte, Chungchandev, Joenunezb, and Amauragis.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="margin-top: 10px; text-align: center; opacity: 0.6; font-size: 0.85em;">
|
||||
v3.0.1
|
||||
v3.1.0
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+30
-30
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
+13
-13
@@ -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) {
|
||||
|
||||
+4
-1
@@ -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."
|
||||
}
|
||||
|
||||
+4
-1
@@ -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。"
|
||||
}
|
||||
|
||||
@@ -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<string|null>} 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);
|
||||
|
||||
@@ -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 };
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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');
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 += '</div>'; // 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() {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+42
-42
@@ -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 = $('<div class="rpg-mobile-overlay"></div>');
|
||||
$('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;
|
||||
}
|
||||
|
||||
|
||||
+51
-54
@@ -55,13 +55,13 @@ export function setupMobileToggle() {
|
||||
const $overlay = $('<div class="rpg-mobile-overlay"></div>');
|
||||
|
||||
// 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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -357,7 +357,7 @@ export function migrateCharactersToJSON(textData) {
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
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');
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
+6
-1
@@ -935,9 +935,14 @@
|
||||
<li>Fixed smaller bugs.</li>
|
||||
</ul>
|
||||
|
||||
<h4 style="margin-top: 20px; margin-bottom: 10px;"><strong data-i18n="settings.recommendedModels.title">Recommended Models:</strong></h4>
|
||||
<p style="margin-left: 20px; line-height: 1.6;" data-i18n="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.
|
||||
</p>
|
||||
|
||||
<h4 style="margin-top: 20px; margin-bottom: 10px;"><strong>Special thanks to all the other contributors for this project:</strong></h4>
|
||||
<p style="margin-left: 20px; line-height: 1.6;">
|
||||
Paperboygold, Munimunigamer, Subarashimo, Lilminzyu, Claude (???), IDeathByte, Chungchandev, Joenunezb, and Amauragis!
|
||||
Paperboygold, Munimunigamer, Subarashimo, Lilminzyu, Claude (???), IDeathByte, Chungchandev, Joenunezb, and Amauragis.
|
||||
</p>
|
||||
|
||||
<div style="margin-top: 20px; text-align: center;">
|
||||
|
||||
Reference in New Issue
Block a user