From e912b4f87da0c592e693b0ef5a66a8843f204a61 Mon Sep 17 00:00:00 2001 From: Zack3D Date: Sun, 3 Aug 2025 22:43:53 -0700 Subject: [PATCH] schema res --- html/settings.html | 14 +++++++++ index.js | 72 ++++++++++++++++++++++++++++++++++++++++++++++ src/LLMAdapter.js | 2 +- 3 files changed, 87 insertions(+), 1 deletion(-) diff --git a/html/settings.html b/html/settings.html index 225b119..53cb7bc 100644 --- a/html/settings.html +++ b/html/settings.html @@ -30,5 +30,19 @@ + +
+
+

Model Settings

+

Use structured output for models that support it (e.g., OpenAI, Gemini, Anthropic).

+
+ + +
+
+
\ No newline at end of file diff --git a/index.js b/index.js index a22c4f4..e6ae912 100644 --- a/index.js +++ b/index.js @@ -4,6 +4,7 @@ console.log('RTS-MODE: index.js script loading...'); console.log('RTS-MODE: jQuery available:', typeof jQuery !== 'undefined'); console.log('RTS-MODE: $ available:', typeof $ !== 'undefined'); +import { extension_settings, saveSettingsDebounced } from '../../../script.js'; import { renderExtensionTemplateAsync } from '../../extensions.js'; import { eventSource, event_types } from '../../events.js'; import { createMapCanvas } from './ui/MapCanvas.js'; @@ -21,6 +22,62 @@ console.log('RTS-MODE: All imports successful'); const extensionId = 'rts-mode'; const extensionName = 'RTS Chat Mode'; +// RTS-mode specific settings +const rtsSettings = { + structuredOutput: false, +}; + +// Placeholder for the JSON schema +const RTS_JSON_SCHEMA = { + "type": "object", + "properties": { + "narrative": { + "type": "string", + "description": "The story portion of the turn." + }, + "state": { + "type": "object", + "description": "The complete game state." + }, + "entityUpdates": { + "type": "array", + "description": "A list of entities that have changed.", + "items": { + "type": "object" + } + } + }, + "required": ["narrative", "state"] +}; + + +function isModelCompatible(chatCompletionSettings) { + // TODO: Expand this list with more models that support structured output + const compatibleModels = [ + 'claude-3', + 'gpt-4', + 'gemini', + ]; + + const modelName = chatCompletionSettings.model.toLowerCase(); + return compatibleModels.some(m => modelName.includes(m)); +} + +async function loadRtsSettings() { + // Load settings + Object.assign(rtsSettings, extension_settings[extensionId]); + + // Set UI elements + $('#rts-structured-output-toggle').prop('checked', rtsSettings.structuredOutput); +} + +function onStructuredOutputToggle(event) { + const value = Boolean($(event.target).prop('checked')); + rtsSettings.structuredOutput = value; + extension_settings[extensionId].structuredOutput = value; + saveSettingsDebounced(); +} + let root; let topButton; let uiMounted = false; @@ -143,8 +200,15 @@ async function onRtsUICommand() { jQuery(async function() { console.log('RTS Chat Mode: jQuery ready, initializing extension...'); + + // Load settings + extension_settings[extensionId] = extension_settings[extensionId] || {}; + loadRtsSettings(); await addTopBarButton(); + + // Add event listeners + $('#rts-structured-output-toggle').on('input', onStructuredOutputToggle); // Register slash commands SlashCommandParser.addCommandObject(SlashCommand.fromProps({ @@ -194,4 +258,12 @@ jQuery(async function() { })); console.log('RTS Chat Mode: Extension initialized successfully'); +}); + +eventSource.on(event_types.CHAT_COMPLETION_SETTINGS_READY, (data) => { + const { chatCompletionSettings } = SillyTavern.getContext(); + if (rtsSettings.structuredOutput && isModelCompatible(chatCompletionSettings)) { + data.responseMimeType = "application/json"; + data.responseSchema = RTS_JSON_SCHEMA; + } }); \ No newline at end of file diff --git a/src/LLMAdapter.js b/src/LLMAdapter.js index 93dbd64..56e2b9e 100644 --- a/src/LLMAdapter.js +++ b/src/LLMAdapter.js @@ -102,7 +102,7 @@ export async function sendTurn(userCmd) { throw new Error('LLM returned an empty response.'); } - const responseJson = extractJson(reply); + const responseJson = typeof reply === 'object' ? reply : extractJson(reply); if (responseJson && responseJson.state && responseJson.narrative) { console.log('RTS: Processing AI response with state:', responseJson.state);