diff --git a/cursor-auto-resume.js b/cursor-auto-resume.js index 2b054db..a068bb6 100644 --- a/cursor-auto-resume.js +++ b/cursor-auto-resume.js @@ -1,12 +1,90 @@ -// Ultra-simple Cursor Auto Resume Script - Copy & paste into browser console +// Enhanced Cursor Auto Resume Script with UI Control (function() { - console.log('Cursor Auto Resume: Running'); + console.log('Cursor Auto Resume: Enhanced version running'); - // Track last click time to avoid multiple clicks + // State management + let isActive = true; // Script starts active by default let lastClickTime = 0; + let injectedButton = null; + + // Button injection and management + function createInfinityButton() { + const button = document.createElement('div'); + button.className = 'anysphere-icon-button bg-[transparent] border-none text-foreground flex w-3 items-center justify-center cursor-auto-resume-btn'; + button.style.cursor = 'pointer'; + button.title = isActive ? 'Auto-resume is ON - Click to disable' : 'Auto-resume is OFF - Click to enable'; + + const icon = document.createElement('span'); + icon.className = 'codicon codicon-infinity !text-[12px] none'; + + button.appendChild(icon); + updateButtonAppearance(button); + + // Add click handler + button.addEventListener('click', toggleAutoResume); + + return button; + } + + function updateButtonAppearance(button) { + if (!button) return; + + const icon = button.querySelector('.codicon-infinity'); + if (isActive) { + // Active state - bright white like native hover + button.style.opacity = '1'; + button.style.color = '#ffffff'; + icon.style.color = '#ffffff'; + button.title = 'Auto-resume is ON - Click to disable'; + } else { + // Disabled state - dimmed + button.style.opacity = '0.5'; + button.style.color = '#888'; + icon.style.color = '#888'; + button.title = 'Auto-resume is OFF - Click to enable'; + } + } + + function injectButton() { + // Remove existing button if it exists + const existingButton = document.querySelector('.cursor-auto-resume-btn'); + if (existingButton) { + existingButton.remove(); + } + + // Find the button container + const buttonContainer = document.querySelector('.button-container.composer-button-area'); + if (!buttonContainer) { + console.log('Button container not found, will retry...'); + return false; + } + + // Find the image button to insert before it + const imageButton = buttonContainer.querySelector('.codicon-image-two')?.closest('.anysphere-icon-button'); + if (!imageButton) { + console.log('Image button not found, will retry...'); + return false; + } + + // Create and inject the infinity button + injectedButton = createInfinityButton(); + buttonContainer.insertBefore(injectedButton, imageButton); + + console.log('Infinity button injected successfully'); + return true; + } + + function toggleAutoResume() { + isActive = !isActive; + console.log(`Auto-resume ${isActive ? 'enabled' : 'disabled'}`); + updateButtonAppearance(injectedButton); + } // Main function that looks for and clicks the resume link function clickResumeLink() { + // Only proceed if the script is active + if (!isActive) return; + // Prevent clicking too frequently (3 second cooldown) const now = Date.now(); if (now - lastClickTime < 3000) return; @@ -34,10 +112,69 @@ } } - // Run periodically - setInterval(clickResumeLink, 1000); + // Monitor for DOM changes to reinject button when needed + function setupDOMObserver() { + const observer = new MutationObserver((mutations) => { + let shouldReinject = false; + + mutations.forEach((mutation) => { + // Check if button container was added/modified + if (mutation.type === 'childList') { + mutation.addedNodes.forEach((node) => { + if (node.nodeType === Node.ELEMENT_NODE) { + if (node.classList?.contains('composer-button-area') || + node.querySelector?.('.composer-button-area')) { + shouldReinject = true; + } + } + }); + } + }); + + // Check if our button still exists + if (!document.querySelector('.cursor-auto-resume-btn')) { + shouldReinject = true; + } + + if (shouldReinject) { + // Add a small delay to ensure DOM is stable + setTimeout(() => { + injectButton(); + }, 100); + } + }); + + observer.observe(document.body, { + childList: true, + subtree: true + }); + + return observer; + } + + // Initialize the script + function initialize() { + // Try to inject button immediately + if (!injectButton()) { + // If injection fails, retry every second until successful + const retryInterval = setInterval(() => { + if (injectButton()) { + clearInterval(retryInterval); + } + }, 1000); + } + + // Setup DOM observer for reinjection + setupDOMObserver(); + + // Run resume checking periodically + setInterval(clickResumeLink, 1000); + + // Also run once immediately + clickResumeLink(); + } - // Also run once immediately - clickResumeLink(); + // Start the script + initialize(); })(); \ No newline at end of file diff --git a/cursor-auto-resume.min.js b/cursor-auto-resume.min.js index 89d6d2c..196f45c 100644 --- a/cursor-auto-resume.min.js +++ b/cursor-auto-resume.min.js @@ -1 +1 @@ -!function(){console.log("Cursor Auto Resume: Running");let t=0;function e(){const e=Date.now();if(e-t<3e3)return;const n=document.querySelectorAll("body *");for(const o of n)if(o&&o.textContent&&(o.textContent.includes("stop the agent after 25 tool calls")||o.textContent.includes("Note: we default stop"))){const n=o.querySelectorAll('a, span.markdown-link, [role="link"], [data-link]');for(const o of n)if("resume the conversation"===o.textContent.trim())return console.log('Clicking "resume the conversation" link'),o.click(),void(t=e)}}setInterval(e,1e3),e()}(); \ No newline at end of file +(function(){console.log("Cursor Auto Resume: Enhanced version running");let e=!0,t=0,n=null;function o(){const t=document.createElement("div");t.className="anysphere-icon-button bg-[transparent] border-none text-foreground flex w-3 items-center justify-center cursor-auto-resume-btn",t.style.cursor="pointer",t.title=e?"Auto-resume is ON - Click to disable":"Auto-resume is OFF - Click to enable";const n=document.createElement("span");return n.className="codicon codicon-infinity !text-[12px] none",t.appendChild(n),s(t),t.addEventListener("click",c),t}function s(t){if(!t)return;const n=t.querySelector(".codicon-infinity");e?(t.style.opacity="1",t.style.color="#ffffff",n.style.color="#ffffff",t.title="Auto-resume is ON - Click to disable"):(t.style.opacity="0.5",t.style.color="#888",n.style.color="#888",t.title="Auto-resume is OFF - Click to enable")}function i(){const e=document.querySelector(".cursor-auto-resume-btn");e&&e.remove();const t=document.querySelector(".button-container.composer-button-area");if(!t)return console.log("Button container not found, will retry..."),!1;const s=t.querySelector(".codicon-image-two")?.closest(".anysphere-icon-button");return s?(n=o(),t.insertBefore(n,s),console.log("Infinity button injected successfully"),!0):(console.log("Image button not found, will retry..."),!1)}function c(){e=!e,console.log(`Auto-resume ${e?"enabled":"disabled"}`),s(n)}function r(){if(!e)return;const n=Date.now();if(n-t<3e3)return;const o=document.querySelectorAll("body *");for(const e of o){if(!e||!e.textContent)continue;if(e.textContent.includes("stop the agent after 25 tool calls")||e.textContent.includes("Note: we default stop")){const o=e.querySelectorAll("a, span.markdown-link, [role=\"link\"], [data-link]");for(const e of o)if("resume the conversation"===e.textContent.trim())return console.log('Clicking "resume the conversation" link'),e.click(),void(t=n)}}}function l(){const e=new MutationObserver((e=>{let t=!1;e.forEach((e=>{"childList"===e.type&&e.addedNodes.forEach((e=>{e.nodeType===Node.ELEMENT_NODE&&(e.classList?.contains("composer-button-area")||e.querySelector?.(".composer-button-area"))&&(t=!0)}))})),document.querySelector(".cursor-auto-resume-btn")||(t=!0),t&&setTimeout((()=>{i()}),100)}));return e.observe(document.body,{childList:!0,subtree:!0}),e}!function(){if(!i()){const e=setInterval((()=>{i()&&clearInterval(e)}),1e3)}l(),setInterval(r,1e3),r()}()})(); \ No newline at end of file