From 5d117e50b912f59fd7263993235ab1db0ee7158c Mon Sep 17 00:00:00 2001 From: "russell@unturf.com" Date: Mon, 23 Feb 2026 19:55:28 -0500 Subject: [PATCH] Namespace globals under window.uncloseai to stop clobbering host pages window.sendMessage, window.handleUserInput, window.speakText etc were overwriting host page functions with the same names. This broke OpenCompletion chat (sendMessage clobbered). Now all exports live under window.uncloseai namespace. Only uniquely-named globals (UncloseVault, toggleUncloseaiEmbeddedModal, openTTSModal, etc) remain on window directly for internal cross-module compat. --- public/src/widget-library.js | 2 +- public/uncloseai.js | 45 ++++++++++++++++++++++++------------ 2 files changed, 31 insertions(+), 16 deletions(-) diff --git a/public/src/widget-library.js b/public/src/widget-library.js index d787b5d..2175cce 100644 --- a/public/src/widget-library.js +++ b/public/src/widget-library.js @@ -129,7 +129,7 @@ export function createChatFeature(container) {

AI Chat

- + `; container.appendChild(chatDiv); } diff --git a/public/uncloseai.js b/public/uncloseai.js index bb24395..01cd593 100644 --- a/public/uncloseai.js +++ b/public/uncloseai.js @@ -157,25 +157,40 @@ export { chatHistory } from "./src/chat.js"; // ------------------------- if (!__alreadyLoaded) { - // Export functions to global scope for HTML onclick handlers - window.handleUserInput = Chat.handleUserInput; - window.readPageWithHermes = PageReader.readPageWithHermes; - window.sendMessage = Chat.sendMessage; - window.speakText = TTS.speakText; - window.uploadFile = FileUpload.uploadFile; - window.openTTSModal = UI.openTTSModal; - window.openTranslateModal = UI.openTranslateModal; + // Export ALL functions under window.uncloseai namespace to avoid clobbering + // host page globals (e.g. a page's own sendMessage, speakText, etc.) + window.uncloseai = { + handleUserInput: Chat.handleUserInput, + readPageWithHermes: PageReader.readPageWithHermes, + sendMessage: Chat.sendMessage, + speakText: TTS.speakText, + uploadFile: FileUpload.uploadFile, + openTTSModal: UI.openTTSModal, + openTranslateModal: UI.openTranslateModal, + toggleUncloseaiEmbeddedModal: async () => + await UI.toggleUncloseaiEmbeddedModal(), + extractWebpageContent: Content.extractWebpageContent, + getSelectedModel: Models.getSelectedModel, + getSelectedModelEndpoint: Models.getSelectedModelEndpoint, + showProgressIndicator: FileUpload.showProgressIndicator, + hideProgressIndicator: FileUpload.hideProgressIndicator, + handleTTSFromElement: UI.handleTTSFromElement, + handleUploadFromElement: UI.handleUploadFromElement, + handleSmartTranslate: UI.handleSmartTranslate, + UncloseVault: UncloseVault, + }; + + // Only set uniquely-named globals that internal extension modules depend on. + // NEVER set generic names (sendMessage, speakText, handleUserInput, uploadFile, + // getSelectedModel, etc.) directly on window — they clobber host page functions. + window.UncloseVault = UncloseVault; window.toggleUncloseaiEmbeddedModal = async () => await UI.toggleUncloseaiEmbeddedModal(); - window.extractWebpageContent = Content.extractWebpageContent; - window.getSelectedModel = Models.getSelectedModel; - window.getSelectedModelEndpoint = Models.getSelectedModelEndpoint; - window.showProgressIndicator = FileUpload.showProgressIndicator; - window.hideProgressIndicator = FileUpload.hideProgressIndicator; + window.openTTSModal = UI.openTTSModal; + window.openTranslateModal = UI.openTranslateModal; window.handleTTSFromElement = UI.handleTTSFromElement; window.handleUploadFromElement = UI.handleUploadFromElement; window.handleSmartTranslate = UI.handleSmartTranslate; - window.UncloseVault = UncloseVault; // Initialize on page load window.addEventListener("load", async () => { @@ -213,7 +228,7 @@ if (!__alreadyLoaded) { }); // Export helper functions for class-based integrations - window.handleCustomChat = async (button) => { + window.uncloseai.handleCustomChat = async (button) => { const container = button.parentElement; const input = container.querySelector("[data-chat-input]"); const chatBox = container.querySelector("[data-chat-box]");