// ==UserScript== // @name Google AI Studio | Clear Chat Button // @namespace http://violentmonkey.net/ // @version 1.5 // @description Automates clicking chat turn options and delete buttons in Gemini. // @author Vibe-Coded by Piknockyou // @license MIT // @match https://aistudio.google.com/* // @icon https://www.google.com/s2/favicons?sz=64&domain=aistudio.google.com // @grant GM_addStyle // @run-at document-idle // @downloadURL https://update.greasyfork.icu/scripts/548206/Google%20AI%20Studio%20%7C%20Clear%20Chat%20Button.user.js // @updateURL https://update.greasyfork.icu/scripts/548206/Google%20AI%20Studio%20%7C%20Clear%20Chat%20Button.meta.js // ==/UserScript== (function() { 'use strict'; // Exit if running in an iframe to avoid duplicate script execution if (window.self !== window.top) { console.log('[Gemini Chat Cleaner] Exiting script in iframe.'); return; } console.log('[Gemini Chat Cleaner] Script loaded and starting...'); console.log('[Gemini Chat Cleaner] Current URL:', window.location.href); //================================================================================ // CONFIGURATION - All settings, selectors, and values that might need to be changed. //================================================================================ const CHAT_TURN_OPTIONS_SELECTOR = 'ms-chat-turn-options span[class="material-symbols-outlined notranslate ms-button-icon-symbol ng-star-inserted"]'; const DELETE_BUTTON_MENU_SELECTOR = 'div.mat-mdc-menu-content > button:first-of-type'; const DELETE_BUTTON_TEXT = "delete Delete"; //================================================================================ // STYLES - CSS for the toolbar button (minimal, uses existing toolbar styles) //================================================================================ GM_addStyle(` #gemini-cleaner-button { margin: 0 4px; color: red !important; } `); //================================================================================ // HELPER FUNCTIONS - Reusable utility functions //================================================================================ /** * Clicks all elements matching a given CSS selector. * @param {string} selector The CSS selector for the elements to click. */ function clickAllElements(selector) { try { const elements = document.querySelectorAll(selector); if (elements.length === 0) { console.warn(`[Gemini Chat Cleaner] No elements found for selector: ${selector}`); return; } elements.forEach(element => { element.click(); }); console.log(`[Gemini Chat Cleaner] Clicked ${elements.length} elements for selector: ${selector}`); } catch (error) { console.error(`[Gemini Chat Cleaner] Error clicking elements for selector ${selector}:`, error); } } /** * Clicks delete buttons within a menu content, identified by specific text. * @param {string} selector The CSS selector for the menu buttons. * @param {string} text The text content to match for the delete button. */ function clickDeleteButtonsInMenu(selector, text) { try { const elements = document.querySelectorAll(selector); if (elements.length === 0) { console.warn(`[Gemini Chat Cleaner] No menu elements found for selector: ${selector}`); return; } elements.forEach(element => { if (element.textContent.trim() === text) { element.click(); console.log(`[Gemini Chat Cleaner] Clicked delete button with text: "${text}"`); } }); } catch (error) { console.error(`[Gemini Chat Cleaner] Error clicking delete buttons in menu for selector ${selector}:`, error); } } /** * Creates and appends a floating button to trigger the cleaning functionality. */ function createToolbarButton() { const toolbarRight = document.querySelector('ms-toolbar .toolbar-right'); // If the toolbar isn't ready, or the button already exists, do nothing. if (!toolbarRight || document.getElementById('gemini-cleaner-button')) { return; } console.log('[Gemini Chat Cleaner] Toolbar found, creating button...'); const button = document.createElement('button'); button.id = 'gemini-cleaner-button'; button.title = 'Clear Chat Turns'; button.setAttribute('ms-button', ''); button.setAttribute('variant', 'icon-borderless'); button.setAttribute('mattooltip', 'Clear Chat Turns'); button.setAttribute('mattooltipposition', 'below'); button.setAttribute('iconname', 'refresh'); button.className = 'mat-mdc-tooltip-trigger ng-tns-c2648639672-5 ms-button-borderless ms-button-icon ng-star-inserted'; button.setAttribute('aria-label', 'Clear Chat Turns'); button.setAttribute('aria-disabled', 'false'); button.addEventListener('click', main); const iconSpan = document.createElement('span'); iconSpan.className = 'material-symbols-outlined notranslate ms-button-icon-symbol ng-star-inserted'; iconSpan.setAttribute('aria-hidden', 'true'); iconSpan.textContent = 'refresh'; button.appendChild(iconSpan); const moreButton = toolbarRight.querySelector('button[iconname="more_vert"]'); if (moreButton) { toolbarRight.insertBefore(button, moreButton); console.log('[Gemini Chat Cleaner] Button inserted before more_vert button.'); } else { toolbarRight.appendChild(button); console.log('[Gemini Chat Cleaner] Button appended to toolbar.'); } // Verify button is in DOM setTimeout(() => { if (document.getElementById('gemini-cleaner-button')) { console.log('[Gemini Chat Cleaner] Button successfully added to toolbar.'); } else { console.error('[Gemini Chat Cleaner] Button not found in toolbar after append.'); } }, 100); } //================================================================================ // MAIN EXECUTION - Core logic of the script //================================================================================ function main() { console.log('[Gemini Chat Cleaner] Main function triggered'); // Click all chat turn option icons clickAllElements(CHAT_TURN_OPTIONS_SELECTOR); // Click delete buttons in menu content clickDeleteButtonsInMenu(DELETE_BUTTON_MENU_SELECTOR, DELETE_BUTTON_TEXT); } // --- MutationObserver to watch for toolbar changes --- const observer = new MutationObserver((mutationsList) => { for (const mutation of mutationsList) { if (mutation.type === 'childList') { for (const node of mutation.addedNodes) { if (node.nodeType === 1 && (node.tagName === 'MS-TOOLBAR' || node.querySelector('ms-toolbar'))) { // The toolbar was added, so try to add our button. createToolbarButton(); return; // Exit after finding the toolbar } } } } }); // --- Initial Execution --- function initialize() { // Try to add the button immediately in case the toolbar is already there. createToolbarButton(); // Start observing the body for changes. observer.observe(document.body, { childList: true, subtree: true }); console.log('[Gemini Chat Cleaner] MutationObserver started.'); } initialize(); })();