Automates clicking chat turn options and delete buttons in Gemini.
// ==UserScript==
// @name Google AI Studio | Clear Chat Button
// @namespace http://violentmonkey.net/
// @version 1.3
// @description Automates clicking chat turn options and delete buttons in Gemini.
// @author Vibecoded by Piknockyou
// @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
// ==/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;
}
`);
//================================================================================
// 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();
})();