Update HTML prompt wording and improve together mode swipe handling

This commit is contained in:
Spicy_Marinara
2025-11-20 22:59:31 +01:00
parent 2b45dc8fae
commit 76c7e3cd9c
3 changed files with 57 additions and 39 deletions
+1 -6
View File
@@ -94,12 +94,7 @@ export async function sendPlotProgression(type) {
// Add HTML prompt if enabled // Add HTML prompt if enabled
if (extensionSettings.enableHtmlPrompt) { if (extensionSettings.enableHtmlPrompt) {
prompt += '\n\n' + `If appropriate, include inline HTML, CSS, and JS elements for creative, visual storytelling throughout your response: prompt += '\n\n' + `If appropriate, include inline HTML, CSS, and JS segments whenever they enhance visual storytelling (e.g., for in-world screens, posters, books, letters, signs, crests, labels, etc.). Style them to match the setting's theme (e.g., fantasy, sci-fi), keep the text readable, and embed all assets directly (using inline SVGs only with no external scripts, libraries, or fonts). Use these elements freely and naturally within the narrative as characters would encounter them, including animations, 3D effects, pop-ups, dropdowns, websites, and so on. Do not wrap the HTML/CSS/JS in code fences!`;
- Use them liberally to depict any in-world content that can be visualized (screens, posters, books, signs, letters, logos, crests, seals, medallions, labels, etc.), with creative license for animations, 3D effects, pop-ups, dropdowns, websites, and so on.
- Style them thematically to match the theme (e.g., sleek for sci-fi, rustic for fantasy), ensuring text is visible.
- Embed all resources directly (e.g., inline SVGs) so nothing relies on external fonts or libraries.
- Place elements naturally in the narrative where characters would see or use them, with no limits on format or application.
- These HTML/CSS/JS elements must be rendered directly without enclosing them in code fences.`;
} }
// Set flag to indicate we're doing plot progression // Set flag to indicate we're doing plot progression
+41 -23
View File
@@ -110,16 +110,46 @@ export function onGenerationStarted(type, data) {
} }
// For TOGETHER mode: Check if we need to commit extension data // For TOGETHER mode: Check if we need to commit extension data
// Same logic as separate mode - commit on new messages, keep existing data on swipes // Only commit when user sends a new message (not on swipes)
if (extensionSettings.generationMode === 'together') { if (extensionSettings.generationMode === 'together') {
if (!lastActionWasSwipe) { if (!lastActionWasSwipe) {
// User sent a new message - commit lastGeneratedData before generation // User sent a new message - commit data from the last assistant message they replied to
// console.log('[RPG Companion] 📝 TOGETHER MODE COMMIT: New message - committing lastGeneratedData'); // This ensures swipes use consistent data from before the first swipe
committedTrackerData.userStats = lastGeneratedData.userStats; console.log('[RPG Companion] 📝 TOGETHER MODE COMMIT: New message - committing from last assistant message');
committedTrackerData.infoBox = lastGeneratedData.infoBox;
committedTrackerData.characterThoughts = lastGeneratedData.characterThoughts; // Find the last assistant message (before the user's new message)
const chat = getContext().chat;
let foundAssistantMessage = false;
for (let i = chat.length - 1; i >= 0; i--) {
const message = chat[i];
if (!message.is_user) {
// Found last assistant message - commit its stored tracker data
if (message.extra && message.extra.rpg_companion_swipes) {
const swipeId = message.swipe_id || 0;
const swipeData = message.extra.rpg_companion_swipes[swipeId];
if (swipeData) {
committedTrackerData.userStats = swipeData.userStats || null;
committedTrackerData.infoBox = swipeData.infoBox || null;
committedTrackerData.characterThoughts = swipeData.characterThoughts || null;
foundAssistantMessage = true;
console.log('[RPG Companion] ✓ Committed tracker data from message swipe', swipeId);
}
}
break;
}
}
// Fallback: if no stored data found, use lastGeneratedData (for first message)
if (!foundAssistantMessage) {
committedTrackerData.userStats = lastGeneratedData.userStats;
committedTrackerData.infoBox = lastGeneratedData.infoBox;
committedTrackerData.characterThoughts = lastGeneratedData.characterThoughts;
console.log('[RPG Companion] ⚠ No stored message data found, using lastGeneratedData as fallback');
}
} else { } else {
// console.log('[RPG Companion] 🔄 TOGETHER MODE SWIPE: Using existing committedTrackerData (no commit)'); console.log('[RPG Companion] 🔄 TOGETHER MODE SWIPE: Using existing committedTrackerData (no commit)');
} }
} }
@@ -184,12 +214,7 @@ export function onGenerationStarted(type, data) {
// Inject HTML prompt separately at depth 0 if enabled (prevents duplication on swipes) // Inject HTML prompt separately at depth 0 if enabled (prevents duplication on swipes)
if (extensionSettings.enableHtmlPrompt && !shouldSuppress) { if (extensionSettings.enableHtmlPrompt && !shouldSuppress) {
const htmlPrompt = `\nIf appropriate, include inline HTML, CSS, and JS elements for creative, visual storytelling throughout your response: const htmlPrompt = `\nIf appropriate, include inline HTML, CSS, and JS segments whenever they enhance visual storytelling (e.g., for in-world screens, posters, books, letters, signs, crests, labels, etc.). Style them to match the setting's theme (e.g., fantasy, sci-fi), keep the text readable, and embed all assets directly (using inline SVGs only with no external scripts, libraries, or fonts). Use these elements freely and naturally within the narrative as characters would encounter them, including animations, 3D effects, pop-ups, dropdowns, websites, and so on. Do not wrap the HTML/CSS/JS in code fences!`;
- Use them liberally to depict any in-world content that can be visualized (screens, posters, books, signs, letters, logos, crests, seals, medallions, labels, etc.), with creative license for animations, 3D effects, pop-ups, dropdowns, websites, and so on.
- Style them thematically to match the theme (e.g., sleek for sci-fi, rustic for fantasy), ensuring text is visible.
- Embed all resources directly (e.g., inline SVGs) so nothing relies on external fonts or libraries.
- Place elements naturally in the narrative where characters would see or use them, with no limits on format or application.
- These HTML/CSS/JS elements must be rendered directly without enclosing them in code fences.`;
setExtensionPrompt('rpg-companion-html', htmlPrompt, extension_prompt_types.IN_CHAT, 0, false); setExtensionPrompt('rpg-companion-html', htmlPrompt, extension_prompt_types.IN_CHAT, 0, false);
// console.log('[RPG Companion] Injected HTML prompt at depth 0 for together mode'); // console.log('[RPG Companion] Injected HTML prompt at depth 0 for together mode');
@@ -202,14 +227,12 @@ export function onGenerationStarted(type, data) {
const contextSummary = generateContextualSummary(); const contextSummary = generateContextualSummary();
if (contextSummary) { if (contextSummary) {
const wrappedContext = `Here is context information about the current scene, and what follows is the last message in the chat history: const wrappedContext = `\nHere is context information about the current scene, and what follows is the last message in the chat history:
<context> <context>
${contextSummary} ${contextSummary}
Ensure these details naturally reflect and influence the narrative. Character behavior, dialogue, and story events should acknowledge these conditions when relevant, such as fatigue affecting performance, low hygiene influencing social interactions, environmental factors shaping the scene, or a character's emotional state coloring their responses. Ensure these details naturally reflect and influence the narrative. Character behavior, dialogue, and story events should acknowledge these conditions when relevant, such as fatigue affecting performance, low hygiene influencing social interactions, environmental factors shaping the scene, or a character's emotional state coloring their responses.
</context> </context>\n\n`;
`;
// Inject context at depth 1 (before last user message) as SYSTEM // Inject context at depth 1 (before last user message) as SYSTEM
// Skip when a guided generation injection is present to avoid conflicting instructions // Skip when a guided generation injection is present to avoid conflicting instructions
@@ -224,12 +247,7 @@ Ensure these details naturally reflect and influence the narrative. Character be
// Inject HTML prompt separately at depth 0 if enabled (same as together mode pattern) // Inject HTML prompt separately at depth 0 if enabled (same as together mode pattern)
if (extensionSettings.enableHtmlPrompt && !shouldSuppress) { if (extensionSettings.enableHtmlPrompt && !shouldSuppress) {
const htmlPrompt = `\nIf appropriate, include inline HTML, CSS, and JS elements for creative, visual storytelling throughout your response: const htmlPrompt = `\nIf appropriate, include inline HTML, CSS, and JS segments whenever they enhance visual storytelling (e.g., for in-world screens, posters, books, letters, signs, crests, labels, etc.). Style them to match the setting's theme (e.g., fantasy, sci-fi), keep the text readable, and embed all assets directly (using inline SVGs only with no external scripts, libraries, or fonts). Use these elements freely and naturally within the narrative as characters would encounter them, including animations, 3D effects, pop-ups, dropdowns, websites, and so on. Do not wrap the HTML/CSS/JS in code fences!`;
- Use them liberally to depict any in-world content that can be visualized (screens, posters, books, signs, letters, logos, crests, seals, medallions, labels, etc.), with creative license for animations, 3D effects, pop-ups, dropdowns, websites, and so on.
- Style them thematically to match the theme (e.g., sleek for sci-fi, rustic for fantasy), ensuring text is visible.
- Embed all resources directly (e.g., inline SVGs) so nothing relies on external fonts or libraries.
- Place elements naturally in the narrative where characters would see or use them, with no limits on format or application.
- These HTML/CSS/JS elements must be rendered directly without enclosing them in code fences.`;
setExtensionPrompt('rpg-companion-html', htmlPrompt, extension_prompt_types.IN_CHAT, 0, false); setExtensionPrompt('rpg-companion-html', htmlPrompt, extension_prompt_types.IN_CHAT, 0, false);
// console.log('[RPG Companion] Injected HTML prompt at depth 0 for separate mode'); // console.log('[RPG Companion] Injected HTML prompt at depth 0 for separate mode');
+15 -10
View File
@@ -310,12 +310,7 @@ export function generateTrackerInstructions(includeHtmlPrompt = true, includeCon
instructions += `\n`; instructions += `\n`;
} }
instructions += `If appropriate, include inline HTML, CSS, and JS elements for creative, visual storytelling throughout your response: instructions += `If appropriate, include inline HTML, CSS, and JS segments whenever they enhance visual storytelling (e.g., for in-world screens, posters, books, letters, signs, crests, labels, etc.). Style them to match the setting's theme (e.g., fantasy, sci-fi), keep the text readable, and embed all assets directly (using inline SVGs only with no external scripts, libraries, or fonts). Use these elements freely and naturally within the narrative as characters would encounter them, including animations, 3D effects, pop-ups, dropdowns, websites, and so on. Do not wrap the HTML/CSS/JS in code fences!`;
- Use them liberally to depict any in-world content that can be visualized (screens, posters, books, signs, letters, logos, crests, seals, medallions, labels, etc.), with creative license for animations, 3D effects, pop-ups, dropdowns, websites, and so on.
- Style them thematically to match the theme (e.g., sleek for sci-fi, rustic for fantasy), ensuring text is visible.
- Embed all resources directly (e.g., inline SVGs) so nothing relies on external fonts or libraries.
- Place elements naturally in the narrative where characters would see or use them, with no limits on format or application.
- These HTML/CSS/JS elements must be rendered directly without enclosing them in code fences.`;
} }
return instructions; return instructions;
@@ -331,6 +326,7 @@ export function generateTrackerInstructions(includeHtmlPrompt = true, includeCon
export function generateContextualSummary() { export function generateContextualSummary() {
// Use COMMITTED data for generation context, not displayed data // Use COMMITTED data for generation context, not displayed data
const userName = getContext().name1; const userName = getContext().name1;
const trackerConfig = extensionSettings.trackerConfig;
let summary = ''; let summary = '';
// Helper function to clean tracker data (remove code fences and separator lines) // Helper function to clean tracker data (remove code fences and separator lines)
@@ -371,12 +367,21 @@ export function generateContextualSummary() {
} }
} }
// Include attributes and dice roll only if there was a dice roll // Include attributes based on settings
if (extensionSettings.lastDiceRoll) { const alwaysSendAttributes = trackerConfig?.userStats?.alwaysSendAttributes;
const roll = extensionSettings.lastDiceRoll; const shouldSendAttributes = alwaysSendAttributes || extensionSettings.lastDiceRoll;
if (shouldSendAttributes) {
const attributesString = buildAttributesString(); const attributesString = buildAttributesString();
summary += `${userName}'s attributes: ${attributesString}\n`; summary += `${userName}'s attributes: ${attributesString}\n`;
summary += `${userName} rolled ${roll.total} on the last ${roll.formula} roll. Based on their attributes, decide whether they succeeded or failed the action they attempted.\n\n`;
// Add dice roll context if there was one
if (extensionSettings.lastDiceRoll) {
const roll = extensionSettings.lastDiceRoll;
summary += `${userName} rolled ${roll.total} on the last ${roll.formula} roll. Based on their attributes, decide whether they succeeded or failed the action they attempted.\n\n`;
} else {
summary += `\n`;
}
} }
return summary.trim(); return summary.trim();