- // ==UserScript==
- // @name Claude Continue Button
- // @name:it Pulsante Continua per Claude
- // @name:es Botón Continuar para Claude
- // @name:fr Bouton Continuer pour Claude
- // @name:de Weiter-Button für Claude
- // @namespace https://greatest.deepsurf.us/users/Flejta
- // @version 1.1.0
- // @description Adds a 'Continue' button to Claude AI chat interface when message length limit is reached. Allows one-click continuation of Claude's response.
- // @description:it Aggiunge un pulsante 'Continua' all'interfaccia di Claude AI quando viene raggiunto il limite di lunghezza. Permette di continuare la risposta di Claude con un solo clic.
- // @description:es Añade un botón 'Continuar' a la interfaz de Claude AI cuando se alcanza el límite de longitud del mensaje. Permite continuar la respuesta de Claude con un solo clic.
- // @description:fr Ajoute un bouton 'Continuer' à l'interface de Claude AI lorsque la limite de longueur du message est atteinte. Permet de continuer la réponse de Claude en un seul clic.
- // @description:de Fügt der Claude AI-Oberfläche eine 'Weiter'-Schaltfläche hinzu, wenn die Nachrichtenlängenbegrenzung erreicht wird. Ermöglicht die Fortsetzung der Antwort von Claude mit einem Klick.
- // @author Flejta
- // @match https://claude.ai/*
- // @icon https://www.google.com/s2/favicons?sz=64&domain=claude.ai
- // @grant none
- // @license MIT
- // @supportURL https://github.com/flejta/claude-scripts/issues
- // @homepageURL https://github.com/flejta/claude-scripts
- // ==/UserScript==
-
- (function() {
- 'use strict';
-
- // Prompts in different languages
- const continuePrompts = {
- 'en': "Your platform informs me that you've reached the maximum message length and has paused your response. Please continue from where you left off, and if you were working on an artifact, please continue updating the same one instead of starting over.",
- 'it': "La tua piattaforma mi informa che hai raggiunto la lunghezza massima per un messaggio e ha messo in pausa la risposta. Per favore continua da dove eri rimasto, se stavi lavorando su un artefatto continua ad aggiornare lo stesso e non ricominciare da capo.",
- 'es': "Tu plataforma me informa que has alcanzado la longitud máxima del mensaje y ha pausado tu respuesta. Por favor, continúa desde donde lo dejaste, y si estabas trabajando en un artefacto, continúa actualizando el mismo en lugar de empezar de nuevo.",
- 'fr': "Votre plateforme m'informe que vous avez atteint la longueur maximale du message et a mis votre réponse en pause. Veuillez continuer là où vous vous êtes arrêté, et si vous travailliez sur un artefact, veuillez continuer à mettre à jour le même au lieu de recommencer.",
- 'de': "Ihre Plattform teilt mir mit, dass Sie die maximale Nachrichtenlänge erreicht haben und Ihre Antwort pausiert wurde. Bitte fahren Sie dort fort, wo Sie aufgehört haben, und wenn Sie an einem Artefakt gearbeitet haben, aktualisieren Sie bitte dasselbe, anstatt von vorne zu beginnen."
- };
-
- // Warning messages to detect in different languages
- const warningMessages = {
- 'en': /Claude has reached the maximum message length and has paused the response|has reached its response length limit/i,
- 'it': /Claude ha raggiunto la lunghezza massima per un messaggio e ha messo in pausa la risposta/i,
- 'es': /Claude ha alcanzado la longitud máxima del mensaje y ha pausado la respuesta/i,
- 'fr': /Claude a atteint la longueur maximale du message et a mis en pause la réponse/i,
- 'de': /Claude hat die maximale Nachrichtenlänge erreicht und hat die Antwort pausiert/i
- };
-
- // Get user's browser language (default to English if not supported)
- const browserLang = navigator.language.split('-')[0];
- const continuePrompt = continuePrompts[browserLang] || continuePrompts['en'];
-
- // Function to wait for an element to appear in the DOM
- function waitForElement(selector, callback, checkFrequencyInMs = 100, timeoutInMs = 10000) {
- let startTimeInMs = Date.now();
- (function loopSearch() {
- if (Date.now() - startTimeInMs > timeoutInMs) {
- console.log("Element search timed out for: ", selector);
- return;
- }
- const element = document.querySelector(selector);
- if (element) {
- callback(element);
- return;
- } else {
- setTimeout(loopSearch, checkFrequencyInMs);
- }
- })();
- }
-
- // Function to create the Continue button for the input area
- function createContinueButton() {
- // Create a new container div for the button (similar to existing divs)
- const buttonContainer = document.createElement('div');
- buttonContainer.className = 'relative shrink-0';
- buttonContainer.innerHTML = `
- <div>
- <div class="flex items-center">
- <div class="flex shrink-0" style="opacity: 1; transform: none; transform-origin: 50% 50% 0px;">
- <button class="inline-flex items-center justify-center relative shrink-0 can-focus select-none disabled:pointer-events-none disabled:opacity-50 disabled:shadow-none disabled:drop-shadow-none border-0.5 transition-all h-8 min-w-8 rounded-lg flex items-center px-[7.5px] group !pointer-events-auto text-text-300 border-border-300 active:scale-[0.98] hover:text-text-200/90 hover:bg-bg-100"
- type="button"
- id="claude-continue-button"
- aria-label="Continue"
- title="Ask Claude to continue">
- <div class="flex flex-row items-center justify-center gap-1">
- <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 256 256">
- <path d="M221.66,133.66l-72,72a8,8,0,0,1-11.32-11.32L196.69,136H40a8,8,0,0,1,0-16H196.69L138.34,61.66a8,8,0,0,1,11.32-11.32l72,72A8,8,0,0,1,221.66,133.66Z"></path>
- </svg>
- </div>
- </button>
- </div>
- </div>
- </div>
- <div class="w-[20rem] absolute max-w-[calc(100vw-16px)] bottom-10 hidden"></div>
- `;
-
- return buttonContainer;
- }
-
- // Create button for warning message
- function createWarningButton() {
- const button = document.createElement('button');
- button.className = 'claude-warning-continue-button inline-flex items-center justify-center ml-2 px-2 py-1 bg-bg-100 rounded-md hover:bg-bg-200 text-text-200 transition-colors';
- button.title = "Click to continue";
- button.innerHTML = `
- <span class="flex items-center">
- <svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="currentColor" viewBox="0 0 256 256" class="mr-1">
- <path d="M221.66,133.66l-72,72a8,8,0,0,1-11.32-11.32L196.69,136H40a8,8,0,0,1,0-16H196.69L138.34,61.66a8,8,0,0,1,11.32-11.32l72,72A8,8,0,0,1,221.66,133.66Z"></path>
- </svg>
- Continue
- </span>
- `;
- return button;
- }
-
- // Function to insert the continuation text into the ProseMirror editor
- function insertContinueText() {
- // Find the ProseMirror contenteditable element
- const proseMirrorEditor = document.querySelector('div.ProseMirror[contenteditable="true"]');
-
- if (proseMirrorEditor) {
- // Clear the editor and insert the new text
- proseMirrorEditor.innerHTML = `<p>${continuePrompt}</p>`;
-
- // Simulate an input event to activate any listeners
- proseMirrorEditor.dispatchEvent(new Event('input', { bubbles: true }));
-
- // Focus on the editor
- proseMirrorEditor.focus();
-
- // Position the cursor at the end of the text
- const selection = window.getSelection();
- const range = document.createRange();
- const lastChild = proseMirrorEditor.lastChild;
- if (lastChild) {
- range.selectNodeContents(lastChild);
- range.collapse(false); // Collapse to the end
- selection.removeAllRanges();
- selection.addRange(range);
- }
-
- console.log('Continue prompt inserted into the editor');
- } else {
- console.log('ProseMirror editor not found');
- }
- }
-
- // Function to insert the button after the tools button
- function insertContinueButton() {
- waitForElement('#input-tools-menu-trigger', function(toolsButton) {
- // Check if the button doesn't already exist
- if (document.getElementById('claude-continue-button')) {
- return;
- }
-
- // Find the container div of the tools button
- const toolsContainer = toolsButton.closest('.relative.shrink-0');
- if (toolsContainer) {
- // Create and insert the continue button after the tools button
- const continueButton = createContinueButton();
- toolsContainer.parentNode.insertBefore(continueButton, toolsContainer.nextSibling);
-
- // Add event listener to the button
- document.getElementById('claude-continue-button').addEventListener('click', function() {
- insertContinueText();
- });
-
- console.log('Continue button added successfully');
- }
- });
- }
-
- // Function to check for warning messages and add buttons to them
- function checkForWarningMessages() {
- // Get all warning messages
- const warningElements = document.querySelectorAll('[data-testid="message-warning"]');
-
- // Process only the most recent warning if there are multiple
- let latestWarning = null;
-
- warningElements.forEach(warning => {
- // Check if the warning is about message length limit
- const text = warning.textContent || '';
- let isLengthWarning = false;
-
- for (const lang in warningMessages) {
- if (warningMessages[lang].test(text)) {
- isLengthWarning = true;
- break;
- }
- }
-
- // Remove existing buttons from all warnings
- const existingButton = warning.querySelector('.claude-warning-continue-button');
- if (existingButton) {
- existingButton.remove();
- }
-
- // If it's a length warning, mark it as the latest
- if (isLengthWarning) {
- latestWarning = warning;
- }
- });
-
- // Add button only to the latest warning
- if (latestWarning) {
- const p = latestWarning.querySelector('p');
- if (p && !p.querySelector('.claude-warning-continue-button')) {
- const button = createWarningButton();
- p.appendChild(button);
-
- // Add event listener
- button.addEventListener('click', function() {
- insertContinueText();
- });
- }
- }
- }
-
- // Initial setup
- function initialize() {
- insertContinueButton();
- checkForWarningMessages();
- }
-
- // Check if the page is already loaded
- if (document.readyState === 'complete' || document.readyState === 'interactive') {
- initialize();
- } else {
- // Otherwise, wait for the page to fully load
- window.addEventListener('DOMContentLoaded', initialize);
- }
-
- // Periodically check, to handle SPA navigation and dynamic content
- setInterval(function() {
- if (!document.getElementById('claude-continue-button')) {
- insertContinueButton();
- }
- checkForWarningMessages();
- }, 2000);
- })();