diff --git a/index.js b/index.js
index f3f8009..4d28814 100644
--- a/index.js
+++ b/index.js
@@ -1,31 +1,42 @@
// SillyBubble - Dynamic Chat Bubble Image Generation Extension
-import { extension_settings, getContext, loadExtensionSettings, registerCustomFunction } from "../../../extensions.js";
-import { saveSettingsDebounced, callPopup, substituteParams } from "../../../../script.js";
+import { extension_settings, getContext } from "../../../extensions.js";
+import { saveSettingsDebounced, callPopup } from "../../../../script.js";
// Extension configuration
const extensionName = "SillyBubble";
const extensionFolderPath = `scripts/extensions/third-party/${extensionName}`;
-const extensionSettings = extension_settings[extensionName];
+
+// Default settings
const defaultSettings = {
image_service_url: "image.php",
default_style: "default",
enabled: true
};
+// Make sure settings exist
+if (!extension_settings[extensionName]) {
+ extension_settings[extensionName] = {};
+}
+
+// Apply defaults for any missing settings
+if (Object.keys(extension_settings[extensionName]).length === 0) {
+ Object.assign(extension_settings[extensionName], defaultSettings);
+}
+
// Function for AI to call - generates markdown image with URL-encoded text
function generateChatBubbleImage(text, style) {
- if (!extensionSettings.enabled) {
+ if (!extension_settings[extensionName].enabled) {
return text;
}
// Use default style if not specified
- const bubbleStyle = style || extensionSettings.default_style;
+ const bubbleStyle = style || extension_settings[extensionName].default_style;
// URL encode the text parameter
const encodedText = encodeURIComponent(text);
// Construct the URL with the encoded text
- const imageUrl = `${extensionSettings.image_service_url}?q=${encodedText}`;
+ const imageUrl = `${extension_settings[extensionName].image_service_url}?q=${encodedText}`;
// Add style parameter if specified
const fullUrl = bubbleStyle !== "default"
@@ -36,37 +47,32 @@ function generateChatBubbleImage(text, style) {
return ``;
}
-// Load extension settings
-async function loadSettings() {
- extension_settings[extensionName] = extension_settings[extensionName] || {};
- if (Object.keys(extension_settings[extensionName]).length === 0) {
- Object.assign(extension_settings[extensionName], defaultSettings);
- }
-
+// Load extension settings into UI
+function loadSettings() {
// Update UI with current settings
- $("#sillybubble_enabled").prop("checked", extensionSettings.enabled).trigger("input");
- $("#sillybubble_image_url").val(extensionSettings.image_service_url).trigger("input");
- $("#sillybubble_default_style").val(extensionSettings.default_style).trigger("input");
+ $("#sillybubble_enabled").prop("checked", extension_settings[extensionName].enabled).trigger("input");
+ $("#sillybubble_image_url").val(extension_settings[extensionName].image_service_url).trigger("input");
+ $("#sillybubble_default_style").val(extension_settings[extensionName].default_style).trigger("input");
}
// Handle enable/disable toggle
function onEnabledInput(event) {
const value = Boolean($(event.target).prop("checked"));
- extensionSettings.enabled = value;
+ extension_settings[extensionName].enabled = value;
saveSettingsDebounced();
}
// Handle image service URL changes
function onImageUrlInput(event) {
const value = $(event.target).val();
- extensionSettings.image_service_url = value;
+ extension_settings[extensionName].image_service_url = value;
saveSettingsDebounced();
}
// Handle default style changes
function onDefaultStyleInput(event) {
const value = $(event.target).val();
- extensionSettings.default_style = value;
+ extension_settings[extensionName].default_style = value;
saveSettingsDebounced();
}
@@ -82,63 +88,113 @@ function onTestButtonClick() {
${markdown}
`;
+
callPopup(testPopup, 'text');
}
+// Register function tool
+function registerFunctionTool() {
+ try {
+ // Check if ToolManager exists in global scope
+ if (!window.ToolManager) {
+ console.warn(`[${extensionName}] ToolManager not found. Will try alternative registration methods.`);
+
+ // Method 1: Register directly to window
+ window.generateChatBubbleImage = generateChatBubbleImage;
+ console.log(`[${extensionName}] Registered function to window object`);
+
+ // Method 2: Add to extensions_functions if it exists
+ if (window.extensions_functions) {
+ window.extensions_functions['generateChatBubbleImage'] = generateChatBubbleImage;
+ console.log(`[${extensionName}] Added to extensions_functions`);
+ }
+
+ return;
+ }
+
+ // Check if tool calling is supported
+ if (typeof window.ToolManager.isToolCallingSupported !== 'function' || !window.ToolManager.isToolCallingSupported()) {
+ console.warn(`[${extensionName}] Tool calling is not supported in the current configuration`);
+ return;
+ }
+
+ // Define the function parameters schema
+ const parameters = {
+ "type": "object",
+ "properties": {
+ "text": {
+ "type": "string",
+ "description": "The text to display in the chat bubble"
+ },
+ "style": {
+ "type": "string",
+ "description": "The visual style of the chat bubble (default, modern, retro, minimal)"
+ }
+ },
+ "required": ["text"]
+ };
+
+ // Register the tool
+ window.ToolManager.registerFunctionTool({
+ name: 'generateChatBubbleImage',
+ displayName: 'Generate Chat Bubble',
+ description: 'Creates a markdown image link with the text displayed as a chat bubble',
+ parameters: parameters,
+ action: async (params) => {
+ return generateChatBubbleImage(params.text, params.style);
+ },
+ formatMessage: async (params) => {
+ return `Generating chat bubble with text: "${params.text?.substring(0, 30)}${params.text?.length > 30 ? '...' : ''}"`;
+ }
+ });
+
+ console.log(`[${extensionName}] Function tool registered via ToolManager`);
+ } catch (error) {
+ console.error(`[${extensionName}] Error registering function tool:`, error);
+ }
+}
+
// Initialize extension
jQuery(async () => {
- // Load settings HTML
- const settingsHtml = await $.get(`${extensionFolderPath}/example.html`);
- // Visual extensions go in the right column (extensions_settings2)
- $("#extensions_settings2").append(settingsHtml);
+ console.log(`[${extensionName}] Initializing...`);
- // Register event listeners
- $("#sillybubble_enabled").on("input", onEnabledInput);
- $("#sillybubble_image_url").on("input", onImageUrlInput);
- $("#sillybubble_default_style").on("input", onDefaultStyleInput);
- $("#sillybubble_test_button").on("click", onTestButtonClick);
-
- // Register the custom function for AI to call
- registerCustomFunction({
- name: 'generateChatBubbleImage',
- displayName: 'Generate Chat Bubble Image',
- description: 'Creates a markdown image link with URL-encoded text parameter for dynamic chat bubbles',
- parameters: [
- {
- name: 'text',
- displayName: 'Text',
- description: 'The text to display in the chat bubble',
- type: 'string',
- required: true,
- },
- {
- name: 'style',
- displayName: 'Style',
- description: 'The visual style of the chat bubble (optional)',
- type: 'string',
- required: false,
- }
- ],
- isPublic: true, // Make sure function is exposed to the AI
- run: async function(text, style) {
- return generateChatBubbleImage(text, style);
- }
- });
-
- // Log to console to verify registration
- console.log(`[${extensionName}] Function registered: generateChatBubbleImage`);
-
- // Add to context if needed - this might be required to expose to AI
try {
- const context = getContext();
- if (context && typeof context.addExtensionFunction === 'function') {
- context.addExtensionFunction('generateChatBubbleImage', generateChatBubbleImage);
- console.log(`[${extensionName}] Function added to context: generateChatBubbleImage`);
- }
+ // Load settings HTML
+ const settingsHtml = await $.get(`${extensionFolderPath}/example.html`);
+ // Visual extensions go in the right column (extensions_settings2)
+ $("#extensions_settings2").append(settingsHtml);
+
+ // Register event listeners
+ $("#sillybubble_enabled").on("input", onEnabledInput);
+ $("#sillybubble_image_url").on("input", onImageUrlInput);
+ $("#sillybubble_default_style").on("input", onDefaultStyleInput);
+ $("#sillybubble_test_button").on("click", onTestButtonClick);
+
+ // Wait for the document to fully load before trying to register tools
+ $(document).ready(() => {
+ setTimeout(() => {
+ // Try to register the function tool after a short delay
+ // to ensure all SillyTavern systems are initialized
+ registerFunctionTool();
+
+ // Also add the function to extension context
+ try {
+ const context = getContext();
+ if (context) {
+ // Make the function available to the AI
+ context.generateChatBubbleImage = generateChatBubbleImage;
+ console.log(`[${extensionName}] Function added to context: generateChatBubbleImage`);
+ }
+ } catch (error) {
+ console.error(`[${extensionName}] Error adding function to context:`, error);
+ }
+ }, 2000); // Wait 2 seconds for SillyTavern to initialize
+ });
+
+ // Load settings
+ loadSettings();
+ console.log(`[${extensionName}] Initialization complete`);
} catch (error) {
- console.error(`[${extensionName}] Error adding function to context:`, error);
+ console.error(`[${extensionName}] Initialization error:`, error);
}
-
- // Load settings
- loadSettings();
-});
+});
\ No newline at end of file