Nessun oggetto della modifica
Nessun oggetto della modifica
Riga 336: Riga 336:


       // ======== Invio prompt via proxy sicuro ========
       // ======== Invio prompt via proxy sicuro ========
       async function sendPrompt(){
       <script>
        const ta = $('#mpai-input');
// --- PATCH: sendPrompt con errori visibili ---
        const model = ($('#mpai-model')?.value || 'gpt-4o-2024-05-13').trim();
async function sendPrompt(){
        const temp  = parseFloat($('#mpai-temp')?.value || '0.7') || 0.7;
  const ta = document.querySelector('#mpai-input');
        const sanitizedOnly = !!($('#mpai-sanitized-only')?.checked);
  const model = (document.querySelector('#mpai-model')?.value || 'gpt-4o-2024-05-13').trim();
  const temp  = parseFloat(document.querySelector('#mpai-temp')?.value || '0.7') || 0.7;
  const sanitizedOnly = !!(document.querySelector('#mpai-sanitized-only')?.checked);


        const content = (ta.value || '').trim();
  const content = (ta.value || '').trim();
        if (!content){ ta.focus(); return; }
  if (!content){ ta.focus(); return; }


        // abilita bozza locale se nessun progetto
  // Se non c'è un progetto, usa la bozza locale
        if (!currentProject && !sessionId){
  if (!window.currentProject && !window.sessionId){  
          ensureSession();
    ensureSession();
          loadSession(sessionId);
    loadSession(sessionId);
        }
  }


        // mostra subito il messaggio dell’utente
  // Messaggio utente
        history.push({role:'user', content});
  history.push({role:'user', content});
        appendMsg('user', content);
  appendMsg('user', content);
        ta.value = '';
  ta.value = '';


        // contesto: progetto o sessione locale
  // Contesto
        const contextName = currentProject
  const contextName = (window.currentProject)
          ? ('Progetto: ' + currentProject)
    ? `Progetto: ${window.currentProject}`
          : ('Sessione: ' + (sessionMeta && sessionMeta.title ? sessionMeta.title : 'Nuova conversazione'));
    : `Sessione: ${window.sessionMeta?.title || 'Nuova conversazione'}`;


        const fileNames = attachments.map(a => a.name).join(', ');
  const fileNames = attachments.map(a => a.name).join(', ');
 
  const preface = `${contextName}
        const preface = `${contextName}
File allegati${sanitizedOnly ? ' (sanificati)' : ''}: ${fileNames || 'nessuno'}
File allegati${sanitizedOnly ? ' (sanificati)' : ''}: ${fileNames || 'nessuno'}


Riga 371: Riga 372:
${content}`;
${content}`;


        // placeholder “Elaboro…”
  // Placeholder
        const pending = document.createElement('div');
  const pending = document.createElement('div');
        pending.className = 'mpai-msg';
  pending.className = 'mpai-msg';
        pending.innerHTML = '<em class="muted">Elaboro…</em>';
  pending.innerHTML = '<em class="muted">Elaboro…</em>';
        chatEl.appendChild(pending);
  document.querySelector('#mpai-chat').appendChild(pending);
        chatEl.scrollTop = chatEl.scrollHeight;


        try{
  try{
          const r = await fetch('/dashboard/api/openai_project_gpt.php', {
    const r = await fetch('/dashboard/api/openai_project_gpt.php', {
            method: 'POST',
      method: 'POST',
            headers: { 'Content-Type': 'application/json' },
      headers: { 'Content-Type': 'application/json' },
            credentials: 'include',
      credentials: 'include',      // manda i cookie/credenziali per Basic Auth
            body: JSON.stringify({ model, prompt: preface })
      mode: 'same-origin',
          });
      cache: 'no-store',
      body: JSON.stringify({ model, prompt: preface })
    });


          // gestione 401 (Basic Auth)
    const raw = await r.text();
          if (r.status === 401){
            pending.remove();
            appendMsg('error','Autenticazione richiesta (401). Riprova: comparirà il popup credenziali.');
            return;
          }


          const txt = await r.text();
    // se non è 2xx, mostra status + body grezzo
          let j; try{ j = JSON.parse(txt); } catch { j = { status:'error', raw: txt }; }
    if (!r.ok){
      pending.remove();
      console.error('GPT proxy error', r.status, r.statusText, raw);
      appendMsg('error', `HTTP ${r.status} ${r.statusText}\n\n${raw || '(nessun body)'}`);
      return;
    }


          pending.remove();
    // prova a parse-are il JSON
    let j;
    try { j = JSON.parse(raw); }
    catch(parseErr){
      pending.remove();
      console.error('JSON parse error', parseErr, raw);
      appendMsg('error', `Risposta non in JSON:\n\n${raw.slice(0,1500)}`);
      return;
    }


          if (j.status === 'ok' && j.result){
    pending.remove();
            if (!currentProject && sessionMeta && sessionMeta.title === 'Nuova conversazione'){
 
              sessionMeta.title = (content.slice(0, 48) || 'Nuova conversazione');
    if (j.status === 'ok' && j.result){
              saveSession();
      // aggiorna titolo bozza alla prima risposta
            }
      if (!window.currentProject && window.sessionMeta && window.sessionMeta.title === 'Nuova conversazione'){
            history.push({role:'assistant', content: j.result});
        window.sessionMeta.title = (content.slice(0,48) || 'Nuova conversazione');
            appendMsg('assistant', j.result);
        saveSession && saveSession();
            saveLocal();
          } else {
            const err = j.error || 'Errore sconosciuto';
            history.push({role:'error', content: err});
            appendMsg('error', err + (j.raw ? '\n\nRAW:\n' + j.raw : ''));
            saveLocal();
          }
        } catch(e){
          pending.remove();
          history.push({role:'error', content: e.message});
          appendMsg('error', e.message);
          saveLocal();
        }
       }
       }
      history.push({role:'assistant', content: j.result});
      appendMsg('assistant', j.result);
      saveLocal && saveLocal();
    } else {
      console.error('API said error', j);
      const err = j.error || 'Errore sconosciuto';
      appendMsg('error', `API error: ${err}\n\nRAW:\n${(j.raw||'').slice(0,1500)}`);
    }
  } catch(e){
    pending.remove();
    console.error('Network/JS error', e);
    appendMsg('error', `Errore di rete/JS: ${e.message}`);
  }
}
</script>


      // ======== Bind ========
      document.addEventListener('click', (e)=>{
        if (e.target && e.target.id==='mpai-send') sendPrompt();
        if (e.target && e.target.id==='mpai-project-create') createProject();
        if (e.target && e.target.id==='mpai-new-chat') resetToNewChat();
        if (e.target && e.target.id==='mpai-clear'){
          if (!confirm('Svuotare la conversazione locale?')) return;
          resetToNewChat();
        }
        if (e.target && e.target.id==='mpai-save-as-project'){
          const name = prompt('Nome progetto da creare e salvare questa chat:');
          if (!name) return;
          $('#mpai-project-name').value = name;
          createProject();
        }
      });
      document.addEventListener('keydown', (e)=>{
        const ta = $('#mpai-input');
        if ((e.metaKey||e.ctrlKey) && e.key==='Enter' && document.activeElement===ta){
          e.preventDefault(); sendPrompt();
        }
      });
      // ======== Boot ========
      loadProjects();
      if (!currentProject){ ensureSession(); loadSession(sessionId); }
    })();
  </script>


   <!-- ========== SEZIONI LEGACY (nascoste di default) ========== -->
   <!-- ========== SEZIONI LEGACY (nascoste di default) ========== -->

Versione delle 16:29, 27 set 2025

🔧 Dashboard Operativa – Masticationpedia

Centro di comando per progetti, API, file e backup

🧾 Apri Log Dashboard