diff --git a/Marinara's Spaghetti Recipe.json b/Marinara's Spaghetti Recipe.json new file mode 100644 index 0000000..5f1fccb --- /dev/null +++ b/Marinara's Spaghetti Recipe.json @@ -0,0 +1,72 @@ +{ + "chat_completion_source": "custom", + "openai_model": "gpt-5-2025-08-07", + "claude_model": "claude-sonnet-4-0", + "openrouter_model": "anthropic/claude-sonnet-4.5", + "openrouter_use_fallback": false, + "openrouter_group_models": true, + "openrouter_sort_models": "context_length", + "openrouter_providers": [], + "openrouter_allow_fallbacks": false, + "openrouter_middleout": "off", + "ai21_model": "jamba-1.5-large", + "mistralai_model": "mistral-large-latest", + "cohere_model": "command-r-plus", + "perplexity_model": "", + "groq_model": "llama3-70b-8192", + "xai_model": "grok-3-beta", + "pollinations_model": "openai", + "aimlapi_model": "gpt-4o-mini-2024-07-18", + "electronhub_model": "gpt-4o-mini", + "electronhub_sort_models": "alphabetically", + "electronhub_group_models": false, + "moonshot_model": "kimi-latest", + "fireworks_model": "accounts/fireworks/models/kimi-k2-instruct", + "cometapi_model": "gpt-4o", + "zai_model": "glm-4.6", + "custom_model": "claude-opus-4-1-20250805-thinking-16k-v2", + "custom_prompt_post_processing": "semi", + "google_model": "gemini-2.0-flash-thinking-exp-01-21", + "vertexai_model": "gemini-2.0-flash-001", + "nanogpt_model": "gpt-4o-mini", + "deepseek_model": "chatgpt-4o-latest", + "azure_api_version": "2024-02-15-preview", + "azure_openai_model": "", + "temperature": 1, + "frequency_penalty": 0, + "presence_penalty": 0, + "top_p": 1, + "top_k": 0, + "top_a": 1, + "min_p": 0, + "repetition_penalty": 1, + "openai_max_context": 2000000, + "openai_max_tokens": 8192, + "wrap_in_quotes": false, + "names_behavior": -1, + "send_if_empty": "", + "impersonation_prompt": "Change of plans! Write a response as the user's {{user}} now. Match their style from the conversation history so far.", + "new_chat_prompt": "", + "new_group_chat_prompt": "", + "new_example_chat_prompt": "{{trim}}", + "continue_nudge_prompt": "Your last message got cut off. Continue writing it. Do not include any parts of the original one. Respond with a direct continuation only.", + "bias_preset_selected": "Marinara's Logit Bias", + "max_context_unlocked": false, + "wi_format": "{0}", + "scenario_format": "{{scenario}}", + "personality_format": "{{personality}}{{trim}}", + "group_nudge_prompt": "", + "stream_openai": true, + "show_external_models": false, + "assistant_prefill": "", + "assistant_impersonation": "", + "claude_use_sysprompt": true, + "use_makersuite_sysprompt": false, + "squash_system_messages": true, + "image_inlining": true, + "inline_image_quality": "high", + "bypass_status_check": false, + "continue_prefill": false, + "seed": -1, + "n": 1 +} diff --git a/RPG Companion Regexes.json b/RPG Companion Regexes.json new file mode 100644 index 0000000..544c5b0 --- /dev/null +++ b/RPG Companion Regexes.json @@ -0,0 +1,30 @@ +[ + { + "scriptName": "RPG: Clean HTML (From Outgoing Prompt)", + "findRegex": "/\\s?<(?!\\!--)(?:\"[^\"]*\"|'[^']*'|[^'\">])*>/g", + "replaceString": "", + "trimStrings": [], + "placement": [2], + "disabled": false, + "markdownOnly": false, + "promptOnly": true, + "runOnEdit": true, + "substituteRegex": 0, + "minDepth": null, + "maxDepth": null + }, + { + "scriptName": "RPG: Clean Tracker Blocks (Keeping Last)", + "findRegex": "/```\\n[\\s\\S]*?\\n---\\n[\\s\\S]*?```\\n+/g", + "replaceString": "", + "trimStrings": [], + "placement": [1, 2], + "disabled": false, + "markdownOnly": false, + "promptOnly": true, + "runOnEdit": true, + "substituteRegex": 0, + "minDepth": 3, + "maxDepth": null + } +] diff --git a/index.js b/index.js index f311e44..3200bae 100644 --- a/index.js +++ b/index.js @@ -118,6 +118,9 @@ import { ensureHtmlCleaningRegex, detectConflictingRegexScripts } from './src/sy import { setupMemoryRecollectionButton, updateMemoryRecollectionButton } from './src/systems/features/memoryRecollection.js'; import { initLorebookLimiter } from './src/systems/features/lorebookLimiter.js'; +// Utility modules +import { importAllDefaults } from './src/utils/importDefaults.js'; + // Integration modules import { commitTrackerData, @@ -601,6 +604,14 @@ jQuery(async () => { // Non-critical - continue anyway } + // Import default preset and regexes if user doesn't have them + try { + await importAllDefaults(); + } catch (error) { + console.error('[RPG Companion] Failed to import defaults:', error); + // Non-critical - continue anyway + } + // Register all event listeners try { registerAllEvents({ diff --git a/src/core/persistence.js b/src/core/persistence.js index b590b91..426de9d 100644 --- a/src/core/persistence.js +++ b/src/core/persistence.js @@ -365,7 +365,14 @@ function migrateToTrackerConfig() { extensionSettings.trackerConfig = { userStats: { customStats: [], - showRPGAttributes: true, + rpgAttributes: [ + { id: 'str', name: 'STR', enabled: true }, + { id: 'dex', name: 'DEX', enabled: true }, + { id: 'con', name: 'CON', enabled: true }, + { id: 'int', name: 'INT', enabled: true }, + { id: 'wis', name: 'WIS', enabled: true }, + { id: 'cha', name: 'CHA', enabled: true } + ], statusSection: { enabled: true, showMoodEmoji: true, @@ -423,6 +430,42 @@ function migrateToTrackerConfig() { } } + // Migrate old showRPGAttributes boolean to rpgAttributes array + if (extensionSettings.trackerConfig.userStats.showRPGAttributes !== undefined) { + const shouldShow = extensionSettings.trackerConfig.userStats.showRPGAttributes; + extensionSettings.trackerConfig.userStats.rpgAttributes = [ + { id: 'str', name: 'STR', enabled: shouldShow }, + { id: 'dex', name: 'DEX', enabled: shouldShow }, + { id: 'con', name: 'CON', enabled: shouldShow }, + { id: 'int', name: 'INT', enabled: shouldShow }, + { id: 'wis', name: 'WIS', enabled: shouldShow }, + { id: 'cha', name: 'CHA', enabled: shouldShow } + ]; + delete extensionSettings.trackerConfig.userStats.showRPGAttributes; + console.log('[RPG Companion] Migrated showRPGAttributes to rpgAttributes array'); + } + + // Ensure rpgAttributes exists even if no migration was needed + if (!extensionSettings.trackerConfig.userStats.rpgAttributes) { + extensionSettings.trackerConfig.userStats.rpgAttributes = [ + { id: 'str', name: 'STR', enabled: true }, + { id: 'dex', name: 'DEX', enabled: true }, + { id: 'con', name: 'CON', enabled: true }, + { id: 'int', name: 'INT', enabled: true }, + { id: 'wis', name: 'WIS', enabled: true }, + { id: 'cha', name: 'CHA', enabled: true } + ]; + } + + // Ensure all rpgAttributes have corresponding values in classicStats + if (extensionSettings.classicStats) { + for (const attr of extensionSettings.trackerConfig.userStats.rpgAttributes) { + if (extensionSettings.classicStats[attr.id] === undefined) { + extensionSettings.classicStats[attr.id] = 10; + } + } + } + // Migrate old presentCharacters structure to new format if (extensionSettings.trackerConfig.presentCharacters) { const pc = extensionSettings.trackerConfig.presentCharacters; diff --git a/src/core/state.js b/src/core/state.js index 34e95d5..c115e3b 100644 --- a/src/core/state.js +++ b/src/core/state.js @@ -71,8 +71,15 @@ export let extensionSettings = { { id: 'hygiene', name: 'Hygiene', enabled: true }, { id: 'arousal', name: 'Arousal', enabled: true } ], - // RPG Attributes toggle - showRPGAttributes: true, + // RPG Attributes (customizable D&D-style attributes) + rpgAttributes: [ + { id: 'str', name: 'STR', enabled: true }, + { id: 'dex', name: 'DEX', enabled: true }, + { id: 'con', name: 'CON', enabled: true }, + { id: 'int', name: 'INT', enabled: true }, + { id: 'wis', name: 'WIS', enabled: true }, + { id: 'cha', name: 'CHA', enabled: true } + ], // Status section config statusSection: { enabled: true, diff --git a/src/systems/rendering/userStats.js b/src/systems/rendering/userStats.js index 12de415..a181ad2 100644 --- a/src/systems/rendering/userStats.js +++ b/src/systems/rendering/userStats.js @@ -86,7 +86,14 @@ export function renderUserStats() { { id: 'hygiene', name: 'Hygiene', enabled: true }, { id: 'arousal', name: 'Arousal', enabled: true } ], - showRPGAttributes: true, + rpgAttributes: [ + { id: 'str', name: 'STR', enabled: true }, + { id: 'dex', name: 'DEX', enabled: true }, + { id: 'con', name: 'CON', enabled: true }, + { id: 'int', name: 'INT', enabled: true }, + { id: 'wis', name: 'WIS', enabled: true }, + { id: 'cha', name: 'CHA', enabled: true } + ], statusSection: { enabled: true, showMoodEmoji: true, customFields: ['Conditions'] }, skillsSection: { enabled: false, label: 'Skills' } }; @@ -171,60 +178,32 @@ export function renderUserStats() { html += ''; // Close rpg-stats-left - // RPG Attributes section (conditionally rendered) - if (config.showRPGAttributes) { + // RPG Attributes section (dynamically generated from config) + const rpgAttributes = config.rpgAttributes || []; + const enabledAttributes = rpgAttributes.filter(attr => attr && attr.enabled && attr.name && attr.id); + + if (enabledAttributes.length > 0) { html += `