SillyBubble/index.js
Sven Olderaan 5ccb1d3984 Fix function registration for AI visibility
- Add isPublic flag to make function visible to AI
- Add explicit context registration for better compatibility
- Add debug logs to help track registration status
- Improve documentation with SillyTavern-specific setup instructions
- Add warning styles for important setup notes

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-03-14 20:57:19 +01:00

145 lines
4.9 KiB
JavaScript

// SillyBubble - Dynamic Chat Bubble Image Generation Extension
import { extension_settings, getContext, loadExtensionSettings, registerCustomFunction } from "../../../extensions.js";
import { saveSettingsDebounced, callPopup, substituteParams } from "../../../../script.js";
// Extension configuration
const extensionName = "SillyBubble";
const extensionFolderPath = `scripts/extensions/third-party/${extensionName}`;
const extensionSettings = extension_settings[extensionName];
const defaultSettings = {
image_service_url: "image.php",
default_style: "default",
enabled: true
};
// Function for AI to call - generates markdown image with URL-encoded text
function generateChatBubbleImage(text, style) {
if (!extensionSettings.enabled) {
return text;
}
// Use default style if not specified
const bubbleStyle = style || extensionSettings.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}`;
// Add style parameter if specified
const fullUrl = bubbleStyle !== "default"
? `${imageUrl}&style=${bubbleStyle}`
: imageUrl;
// Return markdown image format
return `![](${fullUrl})`;
}
// 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);
}
// 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");
}
// Handle enable/disable toggle
function onEnabledInput(event) {
const value = Boolean($(event.target).prop("checked"));
extensionSettings.enabled = value;
saveSettingsDebounced();
}
// Handle image service URL changes
function onImageUrlInput(event) {
const value = $(event.target).val();
extensionSettings.image_service_url = value;
saveSettingsDebounced();
}
// Handle default style changes
function onDefaultStyleInput(event) {
const value = $(event.target).val();
extensionSettings.default_style = value;
saveSettingsDebounced();
}
// Test function to visualize a bubble
function onTestButtonClick() {
const testText = "This is a test chat bubble generated by SillyBubble!";
const markdown = generateChatBubbleImage(testText);
const testPopup = `
<div class="sillybubble-test">
<p>Generated Markdown:</p>
<pre>${markdown.replace(/</g, '&lt;').replace(/>/g, '&gt;')}</pre>
<p>Preview (if connected to image service):</p>
<div>${markdown}</div>
</div>
`;
callPopup(testPopup, 'text');
}
// 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);
// 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`);
}
} catch (error) {
console.error(`[${extensionName}] Error adding function to context:`, error);
}
// Load settings
loadSettings();
});