Claude Internal Chat API

API interna di Claude con form chat - Versione semplificata

// ==UserScript==
// @name         Claude Internal Chat API
// @namespace    http://tampermonkey.net/
// @version      2.0
// @description  API interna di Claude con form chat - Versione semplificata
// @author       Flejta
// @license      MIT
// @match        https://claude.ai/*
// @grant        none
// @run-at       document-idle
// ==/UserScript==

(function() {
    'use strict';

    console.log('💬 Claude Internal Chat API avviato');

    // Configurazione
    const CONFIG = {
        maxTokens: 2000,
        model: 'claude-3-5-sonnet-20241022',
        rateLimit: {
            requests: 3,
            windowMs: 60000 // 1 minuto
        }
    };

    // Stato della chat
    let chatState = {
        messages: [],
        isLoading: false,
        organizationId: null,
        lastRequestTime: [],
        chatVisible: false
    };

    // Funzione per validare gli ID
    function isValidUUID(id) {
        const uuidRegex = /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/i;
        return id && uuidRegex.test(id);
    }

    // Cerca credenziali nei tag script (dalla v1.0)
    function searchScriptTags() {
        const scripts = document.getElementsByTagName('script');
        
        for (let i = 0; i < scripts.length; i++) {
            const content = scripts[i].textContent || scripts[i].innerHTML || '';
            
            // Organization ID
            const orgMatch = content.match(/"organizationID":"([a-f0-9-]+)"/);
            if (orgMatch && isValidUUID(orgMatch[1])) {
                console.log('✅ Org ID trovato:', orgMatch[1]);
                return orgMatch[1];
            }
        }
        
        return null;
    }

    // Intercetta fetch per catturare Organization ID
    function interceptFetch() {
        const originalFetch = window.fetch;
        window.fetch = function(...args) {
            const [url, options] = args;
            
            if (typeof url === 'string') {
                const orgMatch = url.match(/\/organizations\/([a-f0-9-]+)/);
                if (orgMatch && isValidUUID(orgMatch[1]) && !chatState.organizationId) {
                    chatState.organizationId = orgMatch[1];
                    console.log('✅ Org ID intercettato:', orgMatch[1]);
                    updateStatus('Chat pronta!');
                }
            }
            
            return originalFetch.apply(this, args);
        };
    }

    // Crea UI della chat
    function createChatUI() {
        // Container principale
        const container = document.createElement('div');
        container.id = 'claude-chat-ui';
        container.style.cssText = `
            position: fixed;
            bottom: 20px;
            right: 20px;
            width: 350px;
            height: 500px;
            background: #1a1a1a;
            border-radius: 12px;
            box-shadow: 0 4px 20px rgba(0,0,0,0.5);
            display: flex;
            flex-direction: column;
            z-index: 10000;
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
            display: none;
        `;

        // Header
        const header = document.createElement('div');
        header.style.cssText = `
            padding: 15px;
            background: #2a2a2a;
            border-radius: 12px 12px 0 0;
            display: flex;
            justify-content: space-between;
            align-items: center;
            border-bottom: 1px solid #333;
        `;
        header.innerHTML = `
            <h3 style="margin: 0; color: #60a5fa; font-size: 16px;">💬 Claude Chat</h3>
            <div>
                <button id="new-chat-btn" style="background: #059669; color: white; border: none; padding: 5px 10px; border-radius: 4px; cursor: pointer; margin-right: 5px; font-size: 12px;">Nuova Chat</button>
                <button id="close-chat-btn" style="background: none; border: none; color: #888; cursor: pointer; font-size: 18px;">✖</button>
            </div>
        `;

        // Area messaggi
        const messagesArea = document.createElement('div');
        messagesArea.id = 'chat-messages';
        messagesArea.style.cssText = `
            flex: 1;
            overflow-y: auto;
            padding: 15px;
            background: #0a0a0a;
        `;

        // Area input
        const inputArea = document.createElement('div');
        inputArea.style.cssText = `
            padding: 15px;
            border-top: 1px solid #333;
            background: #1a1a1a;
            border-radius: 0 0 12px 12px;
        `;
        inputArea.innerHTML = `
            <div style="display: flex; gap: 10px;">
                <textarea id="chat-input" placeholder="Scrivi un messaggio..." style="
                    flex: 1;
                    padding: 8px;
                    background: #2a2a2a;
                    color: white;
                    border: 1px solid #444;
                    border-radius: 6px;
                    resize: none;
                    font-family: inherit;
                    font-size: 14px;
                    height: 60px;
                "></textarea>
                <button id="send-btn" style="
                    background: #3b82f6;
                    color: white;
                    border: none;
                    padding: 0 15px;
                    border-radius: 6px;
                    cursor: pointer;
                    font-size: 14px;
                ">Invia</button>
            </div>
            <div id="chat-status" style="margin-top: 8px; font-size: 12px; color: #666;"></div>
        `;

        // Assembla UI
        container.appendChild(header);
        container.appendChild(messagesArea);
        container.appendChild(inputArea);
        document.body.appendChild(container);

        // Event listeners
        document.getElementById('close-chat-btn').onclick = toggleChat;
        document.getElementById('new-chat-btn').onclick = newChat;
        document.getElementById('send-btn').onclick = sendMessage;
        
        // Invio con Enter
        document.getElementById('chat-input').addEventListener('keydown', (e) => {
            if (e.key === 'Enter' && !e.shiftKey) {
                e.preventDefault();
                sendMessage();
            }
        });
    }

    // Crea pulsante toggle chat
    function createToggleButton() {
        const button = document.createElement('button');
        button.id = 'claude-chat-toggle';
        button.style.cssText = `
            position: fixed;
            bottom: 20px;
            right: 20px;
            width: 60px;
            height: 60px;
            background: #3b82f6;
            color: white;
            border: none;
            border-radius: 50%;
            cursor: pointer;
            box-shadow: 0 4px 12px rgba(59, 130, 246, 0.4);
            z-index: 9999;
            font-size: 24px;
        `;
        button.innerHTML = '💬';
        button.onclick = toggleChat;
        
        document.body.appendChild(button);
    }

    // Toggle visualizzazione chat
    function toggleChat() {
        chatState.chatVisible = !chatState.chatVisible;
        const chatUI = document.getElementById('claude-chat-ui');
        const toggleBtn = document.getElementById('claude-chat-toggle');
        
        if (chatState.chatVisible) {
            chatUI.style.display = 'flex';
            toggleBtn.style.display = 'none';
            document.getElementById('chat-input').focus();
        } else {
            chatUI.style.display = 'none';
            toggleBtn.style.display = 'block';
        }
    }

    // Nuova chat
    function newChat() {
        if (confirm('Sei sicuro di voler iniziare una nuova chat?')) {
            chatState.messages = [];
            updateMessagesDisplay();
            updateStatus('Nuova chat iniziata');
        }
    }

    // Aggiorna display messaggi
    function updateMessagesDisplay() {
        const messagesArea = document.getElementById('chat-messages');
        messagesArea.innerHTML = '';
        
        if (chatState.messages.length === 0) {
            messagesArea.innerHTML = '<div style="text-align: center; color: #666; margin-top: 50px;">Inizia una conversazione con Claude!</div>';
            return;
        }
        
        chatState.messages.forEach((msg) => {
            const messageDiv = document.createElement('div');
            messageDiv.style.cssText = `
                margin-bottom: 15px;
                display: flex;
                ${msg.role === 'user' ? 'justify-content: flex-end' : 'justify-content: flex-start'}
            `;
            
            const bubble = document.createElement('div');
            bubble.style.cssText = `
                max-width: 80%;
                padding: 10px 15px;
                border-radius: 12px;
                ${msg.role === 'user' 
                    ? 'background: #3b82f6; color: white; border-bottom-right-radius: 4px;' 
                    : 'background: #2a2a2a; color: #e0e0e0; border-bottom-left-radius: 4px;'}
                word-wrap: break-word;
                font-size: 14px;
                line-height: 1.5;
            `;
            
            bubble.textContent = msg.content;
            messageDiv.appendChild(bubble);
            messagesArea.appendChild(messageDiv);
        });
        
        messagesArea.scrollTop = messagesArea.scrollHeight;
    }

    // Aggiorna status
    function updateStatus(text, isError = false) {
        const statusDiv = document.getElementById('chat-status');
        if (statusDiv) {
            statusDiv.textContent = text;
            statusDiv.style.color = isError ? '#ef4444' : '#666';
        }
    }

    // Invia messaggio
    async function sendMessage() {
        const input = document.getElementById('chat-input');
        const message = input.value.trim();
        
        if (!message || chatState.isLoading) return;
        
        // Controlla Organization ID
        if (!chatState.organizationId) {
            updateStatus('Errore: Organization ID non trovato. Ricarica la pagina.', true);
            return;
        }
        
        // Aggiungi messaggio utente
        chatState.messages.push({ role: 'user', content: message });
        updateMessagesDisplay();
        
        // Pulisci input
        input.value = '';
        input.disabled = true;
        document.getElementById('send-btn').disabled = true;
        chatState.isLoading = true;
        updateStatus('Claude sta pensando...');
        
        try {
            // Chiama API
            const response = await fetch(`/api/organizations/${chatState.organizationId}/proxy/v1/messages`, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'Accept': 'application/json'
                },
                credentials: 'include',
                body: JSON.stringify({
                    model: CONFIG.model,
                    max_tokens: CONFIG.maxTokens,
                    messages: chatState.messages
                })
            });
            
            if (!response.ok) {
                throw new Error(`HTTP ${response.status}`);
            }
            
            const data = await response.json();
            const content = data.content?.[0]?.text || 'Risposta vuota';
            
            // Aggiungi risposta
            chatState.messages.push({ role: 'assistant', content: content });
            updateMessagesDisplay();
            updateStatus('');
            
        } catch (error) {
            console.error('Errore:', error);
            updateStatus(`Errore: ${error.message}`, true);
            chatState.messages.pop(); // Rimuovi messaggio utente
            updateMessagesDisplay();
        } finally {
            input.disabled = false;
            document.getElementById('send-btn').disabled = false;
            chatState.isLoading = false;
            input.focus();
        }
    }

    // Inizializzazione
    function init() {
        console.log('🚀 Inizializzazione Claude Chat...');
        
        // Installa intercettore
        interceptFetch();
        
        // Cerca Organization ID negli script
        const orgId = searchScriptTags();
        if (orgId) {
            chatState.organizationId = orgId;
            console.log('✅ Organization ID iniziale:', orgId);
        }
        
        // Crea UI
        createChatUI();
        createToggleButton();
        
        // Se non abbiamo ancora l'org ID, continua a cercare
        if (!chatState.organizationId) {
            console.log('⏳ Organization ID non trovato, intercettazione attiva...');
            updateStatus('Caricamento... Naviga in un progetto Claude.');
        } else {
            updateStatus('Chat pronta!');
        }
    }

    // ========================================
    // INTERFACCIA GLOBALE PER VB.NET
    // ========================================
    
    window.ClaudeChat = {
        // Invia singolo messaggio
        sendMessage: async function(prompt) {
            if (!chatState.organizationId) {
                return { success: false, error: 'Organization ID non trovato' };
            }
            
            try {
                const response = await fetch(`/api/organizations/${chatState.organizationId}/proxy/v1/messages`, {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json',
                        'Accept': 'application/json'
                    },
                    credentials: 'include',
                    body: JSON.stringify({
                        model: CONFIG.model,
                        max_tokens: CONFIG.maxTokens,
                        messages: [{ role: 'user', content: prompt }]
                    })
                });
                
                if (!response.ok) {
                    throw new Error(`HTTP ${response.status}`);
                }
                
                const data = await response.json();
                const content = data.content?.[0]?.text || '';
                
                return { success: true, content: content };
                
            } catch (error) {
                return { success: false, error: error.message };
            }
        },
        
        // Get Organization ID
        getOrgId: function() {
            return chatState.organizationId;
        },
        
        // Set Organization ID manualmente
        setOrgId: function(orgId) {
            if (isValidUUID(orgId)) {
                chatState.organizationId = orgId;
                updateStatus('Organization ID impostato manualmente');
                return { success: true };
            }
            return { success: false, error: 'Organization ID non valido' };
        }
    };
    
    console.log('🔌 ClaudeChat API disponibile');

    // Avvia quando DOM è pronto
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', init);
    } else {
        setTimeout(init, 100);
    }

})();
长期地址
遇到问题?请前往 GitHub 提 Issues。