Google AI Studio | Clear Chat Button

Automates clicking chat turn options and delete buttons in Gemini.

// ==UserScript==
// @name         Google AI Studio | Clear Chat Button
// @namespace    http://violentmonkey.net/
// @version      1.1
// @description  Automates clicking chat turn options and delete buttons in Gemini.
// @author       Vibecoded by Piknockyou
// @match        https://aistudio.google.com/prompts*
// @match        https://aistudio.google.com/app/prompts/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=aistudio.google.com
// @grant        GM_addStyle
// @run-at       document-idle
// ==/UserScript==

(function() {
    'use strict';
    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;
            }
        `);

        //================================================================================
        // 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() {
            console.log('[Gemini Chat Cleaner] Creating toolbar button...');

            // Wait for toolbar to be available
            const waitForToolbar = () => {
                const toolbarRight = document.querySelector('ms-toolbar .toolbar-right');
                if (!toolbarRight) {
                    console.log('[Gemini Chat Cleaner] Toolbar not ready, waiting...');
                    setTimeout(waitForToolbar, 500);
                    return;
                }

                console.log('[Gemini Chat Cleaner] Toolbar found, creating button...');

                // Check if our button already exists
                if (document.getElementById('gemini-cleaner-button')) {
                    console.log('[Gemini Chat Cleaner] Button already exists');
                    return;
                }

                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);

                // Create the icon span to match the toolbar style
                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'; // Using refresh icon instead of emoji

                button.appendChild(iconSpan);

                // Insert before the "more_vert" button (last button in toolbar)
                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(() => {
                    const addedButton = document.getElementById('gemini-cleaner-button');
                    if (addedButton) {
                        console.log('[Gemini Chat Cleaner] Button successfully added to toolbar');
                    } else {
                        console.error('[Gemini Chat Cleaner] Button not found in toolbar after append');
                    }
                }, 100);
            };

            waitForToolbar();
        }

        //================================================================================
        // 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);
    }

    function init() {
        console.log('[Gemini Chat Cleaner] Initializing...');
        createToolbarButton();
        // Optionally run main on load, or let the button trigger it
        // main();
    }

    // Run the main function when the DOM is ready
    // Using setTimeout to ensure all dynamic elements are loaded (can be adjusted if needed)
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', function() {
            console.log('[Gemini Chat Cleaner] DOMContentLoaded event fired');
            init();
        });
    } else {
        console.log('[Gemini Chat Cleaner] DOM already loaded, initializing immediately');
        init();
    }

})();