Gemini Workspace Auto-Pro

Auto-selects Gemini Pro in chats (if available)

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name         Gemini Workspace Auto-Pro
// @namespace    http://tampermonkey.net/
// @version      1.2
// @description  Auto-selects Gemini Pro in chats (if available)
// @author       Gemini & You
// @match        https://gemini.google.com/*
// @grant        none
// @run-at       document-idle
// @noframes
// ==/UserScript==

(function() {
    'use strict';

    const LOG_PREFIX = "[Gemini3-AutoPro]";

    // --- CONFIGURATION ---
    const PRO_SELECTOR = 'button[data-test-id="bard-mode-option-pro"]';
    const ENEMY_LABELS = ["Fast", "Flash"];
    
    // How long to fight the server after a navigation event (in seconds)
    const WATCHDOG_DURATION_SEC = 30; 

    // --- STATE MANAGEMENT ---
    let lastUrl = location.href;
    let watchdogTimer = 0;
    let isWatchdogActive = true; // Start active on load

    function log(...args) {
        console.log(LOG_PREFIX, ...args);
    }

    function waitFor(selector, timeout = 2000) {
        return new Promise(resolve => {
            if (document.querySelector(selector)) return resolve(document.querySelector(selector));
            const observer = new MutationObserver((mutations, obs) => {
                if (document.querySelector(selector)) {
                    obs.disconnect();
                    resolve(document.querySelector(selector));
                }
            });
            observer.observe(document.body, { childList: true, subtree: true });
            setTimeout(() => { observer.disconnect(); resolve(null); }, timeout);
        });
    }

    async function runEnforcer() {
        // 1. Check for Navigation (User clicked a Gem or changed chat)
        if (location.href !== lastUrl) {
            log("🚀 Navigation detected! Waking up watchdog.");
            lastUrl = location.href;
            isWatchdogActive = true;
            watchdogTimer = 0; // Reset the 30s timer
        }

        // 2. If Watchdog is asleep, do nothing
        if (!isWatchdogActive) return;

        // 3. Increment Timer
        watchdogTimer++;
        if (watchdogTimer > WATCHDOG_DURATION_SEC) {
            log("💤 No activity for 30s. Watchdog going to sleep.");
            isWatchdogActive = false;
            return;
        }

        // 4. THE ENFORCER LOGIC
        // Look for the "Fast" button
        const buttons = Array.from(document.querySelectorAll('button, div[role="button"]'));
        const trigger = buttons.find(b => {
            const text = b.innerText || "";
            return ENEMY_LABELS.some(label => text.includes(label)) && b.offsetParent !== null;
        });

        if (!trigger) return; // Fast button not visible, we are safe.

        // Fast found! Open menu.
        let proOption = document.querySelector(PRO_SELECTOR);
        if (!proOption) {
            // Only log this occasionally to avoid spamming console during the animation
            if (watchdogTimer % 2 === 0) log(`⚔️ Detected 'Fast' mode. Opening menu...`);
            trigger.click();
            proOption = await waitFor(PRO_SELECTOR, 1500);
        }

        if (proOption) {
            log("🎯 Found Pro option. Switching...");
            proOption.click();
            // We do NOT stop the watchdog here. We keep watching for the remainder of the 30s
            // in case the server tries to revert it (hydration).
        } else {
            // Close menu if failed
            trigger.click(); 
        }
    }

    // Run forever, checking every 1 second
    log("Gemini Workspace Auto-Pro v1.2 (SPA-Aware) active.");
    setInterval(runEnforcer, 1000);

})();