391 lines
26 KiB
Plaintext
Executable File
391 lines
26 KiB
Plaintext
Executable File
<?php
|
||
session_start();
|
||
$pdo = new PDO("pgsql:host=localhost;dbname=adx_system", "admin", "admin123");
|
||
$config = [];
|
||
try { $stmt = $pdo->query("SELECT config_key, config_value FROM admin.commonia_config"); while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) $config[$row['config_key']] = $row['config_value']; } catch (Exception $e) {}
|
||
$defaultProvider = $config['default_provider'] ?? 'groq';
|
||
?>
|
||
<!DOCTYPE html>
|
||
<html lang="fr">
|
||
<head>
|
||
<meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||
<title>HAMID - Assistant WEVADS</title>
|
||
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet">
|
||
<style>
|
||
:root{--bg:#f8f8f8;--sidebar:#fff;--chat:#fff;--text:#1a1a1a;--muted:#6b7280;--border:#e5e7eb;--primary:#06b6d4}
|
||
*{margin:0;padding:0;box-sizing:border-box}
|
||
body{font-family:-apple-system,sans-serif;background:var(--bg);color:var(--text);height:100vh;overflow:hidden}
|
||
.app{display:flex;height:100vh}
|
||
.sidebar{width:260px;background:var(--sidebar);border-right:1px solid var(--border);display:flex;flex-direction:column}
|
||
.sidebar-header{padding:1rem}
|
||
.new-chat{width:100%;padding:.75rem 1rem;background:linear-gradient(135deg,#06b6d4,#3b82f6);color:#fff;border:none;border-radius:8px;cursor:pointer;display:flex;align-items:center;gap:.5rem}
|
||
.sidebar-section{padding:.5rem 1rem}
|
||
.sidebar-title{font-size:.7rem;font-weight:600;color:var(--muted);text-transform:uppercase;margin-bottom:.5rem}
|
||
.sidebar-item{display:flex;align-items:center;gap:.75rem;padding:.6rem .75rem;border-radius:6px;color:var(--text);text-decoration:none;font-size:.9rem}
|
||
.sidebar-item:hover{background:#f3f4f6}
|
||
.sidebar-footer{margin-top:auto;padding:1rem;border-top:1px solid var(--border)}
|
||
.sidebar-footer a{display:flex;align-items:center;gap:.5rem;padding:.5rem;color:var(--muted);text-decoration:none;font-size:.85rem}
|
||
.main{flex:1;display:flex;flex-direction:column}
|
||
.header{padding:.75rem 1.5rem;border-bottom:1px solid var(--border);display:flex;align-items:center;justify-content:space-between}
|
||
.header-left{display:flex;align-items:center;gap:.75rem}
|
||
.logo{width:36px;height:36px;border-radius:8px;background:linear-gradient(135deg,#06b6d4,#3b82f6);display:flex;align-items:center;justify-content:center;font-size:1.2rem}
|
||
.header-right{display:flex;align-items:center;gap:.5rem}
|
||
.help-btn{padding:.5rem .75rem;border:1px solid var(--border);background:#fff;border-radius:8px;cursor:pointer}
|
||
.provider-select{position:relative}
|
||
.provider-btn{padding:.5rem 1rem;border:1px solid var(--border);background:#fff;border-radius:8px;cursor:pointer;display:flex;align-items:center;gap:.5rem}
|
||
.provider-btn .dot{width:8px;height:8px;border-radius:50%;background:#10b981}
|
||
.provider-menu{position:absolute;top:100%;right:0;margin-top:.5rem;background:#fff;border:1px solid var(--border);border-radius:12px;box-shadow:0 10px 40px rgba(0,0,0,.15);min-width:280px;z-index:100;display:none}
|
||
.provider-menu.show{display:block}
|
||
.provider-group{padding:.5rem}
|
||
.provider-group-title{padding:.5rem .75rem;font-size:.7rem;font-weight:600;text-transform:uppercase}
|
||
.provider-group-title.free{color:#10b981}
|
||
.provider-group-title.limited{color:#f59e0b}
|
||
.provider-group-title.paid{color:#ef4444}
|
||
.provider-option{display:flex;align-items:center;gap:.75rem;padding:.6rem .75rem;border-radius:8px;cursor:pointer}
|
||
.provider-option:hover{background:#f3f4f6}
|
||
.provider-option.active{background:#e0f2fe}
|
||
.provider-option .icon{font-size:1.25rem}
|
||
.provider-option .info{flex:1}
|
||
.provider-option .name{font-size:.9rem;font-weight:500}
|
||
.provider-option .desc{font-size:.75rem;color:var(--muted)}
|
||
.messages{flex:1;overflow-y:auto;padding:1.5rem}
|
||
.welcome{text-align:center;padding:3rem 1rem}
|
||
.welcome-icon{width:80px;height:80px;background:linear-gradient(135deg,#06b6d4,#3b82f6);border-radius:20px;display:flex;align-items:center;justify-content:center;margin:0 auto 1.5rem;font-size:2.5rem}
|
||
.welcome h2{margin-bottom:.75rem}
|
||
.welcome p{color:var(--muted);margin-bottom:2rem}
|
||
.quick-actions{display:flex;gap:.75rem;justify-content:center;flex-wrap:wrap}
|
||
.quick-btn{padding:.75rem 1.25rem;border:2px solid var(--border);background:#fff;border-radius:10px;cursor:pointer;display:flex;align-items:center;gap:.5rem}
|
||
.quick-btn:hover{border-color:var(--primary);background:#f0fdfa}
|
||
.msg{display:flex;gap:1rem;margin-bottom:1.5rem;max-width:900px;margin-left:auto;margin-right:auto}
|
||
.msg-user{justify-content:flex-end}
|
||
.msg-user .bubble{background:#f3f4f6;padding:.875rem 1rem;border-radius:16px 16px 4px 16px;max-width:70%}
|
||
.msg-assistant{align-items:flex-start}
|
||
.msg-assistant .avatar{width:32px;height:32px;background:linear-gradient(135deg,#06b6d4,#3b82f6);border-radius:8px;display:flex;align-items:center;justify-content:center;font-size:.9rem}
|
||
.msg-assistant .msg-wrap{flex:1;max-width:80%}
|
||
.msg-assistant .msg-content{line-height:1.6}
|
||
.msg-footer{margin-top:.5rem;padding-top:.5rem;border-top:1px solid var(--border);font-size:.7rem;color:var(--muted);display:flex;gap:.4rem;flex-wrap:wrap}
|
||
.msg-footer .tag{padding:.2rem .5rem;border-radius:4px;background:#f3f4f6}
|
||
.msg-footer .tag.prov{background:#dbeafe;color:#1e40af}
|
||
.msg-footer .tag.kb{background:#d1fae5;color:#065f46}
|
||
.typing{display:none;padding:1rem 1.5rem;max-width:900px;margin:0 auto}
|
||
.typing.show{display:flex !important;align-items:center;gap:.75rem}
|
||
.typing-avatar{width:32px;height:32px;background:linear-gradient(135deg,#06b6d4,#3b82f6);border-radius:8px;display:flex;align-items:center;justify-content:center;font-size:.9rem}
|
||
.typing-dots{display:flex;gap:4px;padding:.75rem 1rem;background:#f3f4f6;border-radius:16px}
|
||
.typing-dots span{width:8px;height:8px;background:#94a3b8;border-radius:50%;animation:bounce 1.4s infinite}
|
||
.typing-dots span:nth-child(2){animation-delay:.2s}
|
||
.typing-dots span:nth-child(3){animation-delay:.4s}
|
||
@keyframes bounce{0%,80%,100%{transform:translateY(0)}40%{transform:translateY(-6px)}}
|
||
.input-area{padding:1rem 1.5rem 1.5rem;border-top:1px solid var(--border)}
|
||
.input-wrap{display:flex;gap:.5rem;max-width:900px;margin:0 auto;background:#fff;border:1px solid var(--border);border-radius:12px;padding:.5rem;align-items:flex-end}
|
||
.input-wrap:focus-within{border-color:var(--primary)}
|
||
.input-wrap textarea{flex:1;border:none;outline:none;resize:none;font-size:.95rem;padding:.5rem;max-height:120px}
|
||
.input-btn{width:40px;height:40px;background:none;border:none;color:var(--muted);cursor:pointer;border-radius:8px;font-size:1.1rem}
|
||
.input-btn:hover{background:#f3f4f6;color:var(--primary)}
|
||
.send-btn{width:40px;height:40px;background:linear-gradient(135deg,#06b6d4,#3b82f6);color:#fff;border:none;border-radius:8px;cursor:pointer;display:flex;align-items:center;justify-content:center}
|
||
#artPanel{position:fixed;right:-500px;top:0;width:500px;height:100vh;background:#fff;border-left:1px solid var(--border);display:flex;flex-direction:column;transition:right .3s;z-index:200}
|
||
#artPanel.open{right:0;box-shadow:-5px 0 30px rgba(0,0,0,.1)}
|
||
.art-header{padding:1rem;border-bottom:1px solid var(--border);display:flex;justify-content:space-between}
|
||
.art-close{background:none;border:none;font-size:1.5rem;cursor:pointer;color:var(--muted)}
|
||
#artContent{flex:1;overflow:auto;background:#f8fafc}
|
||
#artContent iframe{width:100%;height:100%;border:none}
|
||
.art-footer{padding:1rem;border-top:1px solid var(--border)}
|
||
.art-footer .btn{padding:.5rem 1rem;border:1px solid var(--border);background:#fff;border-radius:6px;text-decoration:none;color:var(--text);display:inline-flex;align-items:center;gap:.4rem}
|
||
.modal{display:none;position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,.5);z-index:300;align-items:center;justify-content:center}
|
||
.modal.show{display:flex}
|
||
.modal-content{background:#fff;border-radius:16px;padding:2rem;max-width:500px;width:90%}
|
||
.modal-content h3{margin-bottom:1rem}
|
||
.modal-content ul{margin:1rem 0;padding-left:1.5rem}
|
||
.modal-content li{margin-bottom:.5rem;color:var(--muted)}
|
||
.modal-content button{margin-top:1rem;padding:.75rem 1.5rem;background:var(--primary);color:#fff;border:none;border-radius:8px;cursor:pointer}
|
||
@media(max-width:768px){.sidebar{display:none}}
|
||
|
||
.msg-tag{display:inline-block;font-size:10px;padding:2px 6px;border-radius:4px;margin-left:4px}
|
||
.msg-tag.kb{background:#10b981;color:white}
|
||
.msg-tag.ia{background:#8b5cf6;color:white}
|
||
|
||
/* Tools Panel */
|
||
.tools-panel {
|
||
background: rgba(15, 23, 42, 0.95);
|
||
border: 1px solid #334155;
|
||
border-radius: 12px;
|
||
padding: 1rem;
|
||
margin: 0.5rem;
|
||
}
|
||
.tools-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(4, 1fr);
|
||
gap: 0.5rem;
|
||
}
|
||
.tool-btn {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
gap: 0.25rem;
|
||
padding: 0.75rem 0.5rem;
|
||
background: linear-gradient(135deg, #1e293b, #0f172a);
|
||
border: 1px solid #334155;
|
||
border-radius: 8px;
|
||
color: #e2e8f0;
|
||
cursor: pointer;
|
||
transition: all 0.2s;
|
||
font-size: 0.75rem;
|
||
}
|
||
.tool-btn:hover {
|
||
border-color: #06b6d4;
|
||
background: linear-gradient(135deg, #1e3a5f, #0f172a);
|
||
transform: translateY(-2px);
|
||
}
|
||
.tool-btn .icon { font-size: 1.25rem; }
|
||
.tool-btn .label { color: #94a3b8; }
|
||
|
||
.tool-result {
|
||
background: #0f172a;
|
||
border: 1px solid #334155;
|
||
border-radius: 8px;
|
||
padding: 0.75rem;
|
||
margin: 0.5rem 0;
|
||
font-family: monospace;
|
||
font-size: 0.8rem;
|
||
max-height: 200px;
|
||
overflow-y: auto;
|
||
}
|
||
.tool-result pre {
|
||
margin: 0;
|
||
white-space: pre-wrap;
|
||
color: #10b981;
|
||
}
|
||
.tool-header {
|
||
color: #06b6d4;
|
||
font-weight: bold;
|
||
margin-bottom: 0.5rem;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 0.5rem;
|
||
}
|
||
|
||
.quick-actions {
|
||
display: flex;
|
||
gap: 0.5rem;
|
||
padding: 0.5rem;
|
||
overflow-x: auto;
|
||
border-top: 1px solid #334155;
|
||
}
|
||
.quick-action {
|
||
padding: 0.4rem 0.8rem;
|
||
background: rgba(6, 182, 212, 0.1);
|
||
border: 1px solid rgba(6, 182, 212, 0.3);
|
||
border-radius: 20px;
|
||
color: #06b6d4;
|
||
font-size: 0.7rem;
|
||
cursor: pointer;
|
||
white-space: nowrap;
|
||
transition: all 0.2s;
|
||
}
|
||
.quick-action:hover {
|
||
background: rgba(6, 182, 212, 0.2);
|
||
border-color: #06b6d4;
|
||
}
|
||
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="app">
|
||
<div class="sidebar">
|
||
<div class="sidebar-header"><button class="new-chat" onclick="newChat()"><i class="fas fa-plus"></i> Nouvelle conversation</button></div>
|
||
<div class="sidebar-section"><div class="sidebar-title">Outils</div><a href="/ia-tools-test.php" class="sidebar-item"><i class="fas fa-wrench"></i> Test Tools</a><a href="javascript:void(0)" onclick="toggleToolsPanel()" class="sidebar-item" style="background:linear-gradient(135deg,#06b6d4,#3b82f6);color:white"><i class="fas fa-cogs"></i> 🔧 Tools Système</a><a href="/ia-documents.php" class="sidebar-item"><i class="fas fa-folder"></i> Documents</a><a href="/ia-knowledge.php" class="sidebar-item"><i class="fas fa-brain"></i> Knowledge Base</a></div>
|
||
<div class="sidebar-footer"><a href="/ia-index.php"><i class="fas fa-th-large"></i> Index IA</a><a href="/hamid-brain-config.php"><i class="fas fa-cog"></i> Configuration</a></div>
|
||
</div>
|
||
<div class="main">
|
||
<div class="header">
|
||
<div class="header-left"><div class="logo">🧞</div><span style="font-weight:600">HAMID - Assistant WEVADS</span></div>
|
||
<div class="header-right">
|
||
<button class="help-btn" onclick="showHelp()"><i class="fas fa-question-circle"></i> Aide</button>
|
||
<div class="provider-select">
|
||
<button class="provider-btn" onclick="document.getElementById('providerMenu').classList.toggle('show')"><span class="dot"></span><span id="currentProvider"><?= ucfirst($defaultProvider) ?></span><i class="fas fa-chevron-down"></i></button>
|
||
<div class="provider-menu" id="providerMenu">
|
||
<div class="provider-group"><div class="provider-group-title free">✅ Gratuits Illimités</div>
|
||
<div class="provider-option" data-prov="ollama_mini" onclick="selProv('ollama_mini','Ollama Mini')"><span class="icon">⚡</span><div class="info"><div class="name">Ollama Mini</div><div class="desc">Local • Rapide</div></div></div>
|
||
<div class="provider-option" data-prov="ollama" onclick="selProv('ollama','Ollama Mistral')"><span class="icon">🦙</span><div class="info"><div class="name">Ollama Mistral</div><div class="desc">Local • 7B</div></div></div>
|
||
<div class="provider-option" data-prov="deepseek" onclick="selProv('deepseek','DeepSeek')"><span class="icon">🔮</span><div class="info"><div class="name">DeepSeek</div><div class="desc">Cloud • Intelligent</div></div></div>
|
||
<div class="provider-option" data-prov="cerebras" onclick="selProv('cerebras','Cerebras')"><span class="icon">🧠</span><div class="info"><div class="name">Cerebras</div><div class="desc">Ultra rapide</div></div></div>
|
||
<div class="provider-option" data-prov="hyperbolic" onclick="selProv('hyperbolic','Hyperbolic')"><span class="icon">🌀</span><div class="info"><div class="name">Hyperbolic</div><div class="desc">Llama 405B</div></div></div>
|
||
<div class="provider-option" data-prov="mistral" onclick="selProv('mistral','Mistral')"><span class="icon">🇫🇷</span><div class="info"><div class="name">Mistral</div><div class="desc">Français</div></div></div>
|
||
<div class="provider-option" data-prov="cohere" onclick="selProv('cohere','Cohere')"><span class="icon">🔶</span><div class="info"><div class="name">Cohere</div><div class="desc">Command-R+</div></div></div>
|
||
</div>
|
||
<div class="provider-group"><div class="provider-group-title limited">⚠️ Gratuits Limités</div>
|
||
<div class="provider-option" data-prov="groq" onclick="selProv('groq','Groq')"><span class="icon">🚀</span><div class="info"><div class="name">Groq</div><div class="desc">Ultra rapide</div></div></div>
|
||
<div class="provider-option" data-prov="gemini" onclick="selProv('gemini','Gemini')"><span class="icon">💎</span><div class="info"><div class="name">Gemini</div><div class="desc">Google</div></div></div>
|
||
</div>
|
||
<div class="provider-group"><div class="provider-group-title paid">💰 Payants</div>
|
||
<div class="provider-option" data-prov="claude" onclick="selProv('claude','Claude')"><span class="icon">🧠</span><div class="info"><div class="name">Claude</div><div class="desc">Anthropic</div></div></div>
|
||
<div class="provider-option" data-prov="chatgpt" onclick="selProv('chatgpt','ChatGPT')"><span class="icon">🤖</span><div class="info"><div class="name">ChatGPT</div><div class="desc">OpenAI GPT-4</div></div></div>
|
||
<div class="provider-option" data-prov="copilot" onclick="selProv('copilot','Copilot')"><span class="icon">🐙</span><div class="info"><div class="name">GitHub Copilot</div><div class="desc">Code Assistant</div></div></div>
|
||
</div></div></div></div></div>
|
||
<div class="messages" id="msgs">
|
||
<div class="welcome" id="welcome"><div class="welcome-icon">🧞</div><h2>Bonjour, je suis HAMID</h2><p>Assistant IA WEVADS avec génération de documents</p>
|
||
<div class="quick-actions">
|
||
<button class="quick-btn" onclick="sendQuick('Génère un PDF')"><i class="fas fa-file-pdf" style="color:#ef4444"></i> PDF</button>
|
||
<button class="quick-btn" onclick="sendQuick('Génère un document Word')"><i class="fas fa-file-word" style="color:#2563eb"></i> Word</button>
|
||
<button class="quick-btn" onclick="sendQuick('Génère un fichier Excel')"><i class="fas fa-file-excel" style="color:#16a34a"></i> Excel</button>
|
||
<button class="quick-btn" onclick="sendQuick('Génère une présentation')"><i class="fas fa-file-powerpoint" style="color:#ea580c"></i> PPT</button>
|
||
<button class="quick-btn" onclick="sendQuick('Génère un QR code')"><i class="fas fa-qrcode" style="color:#7c3aed"></i> QR</button>
|
||
</div></div></div>
|
||
<div class="typing" id="typing">
|
||
<div class="typing-avatar">🧞</div>
|
||
<div class="typing-dots"><span></span><span></span><span></span></div>
|
||
<span style="color:var(--muted);font-size:.9rem">Réflexion...</span>
|
||
</div>
|
||
<div class="input-area"><div class="input-wrap">
|
||
<button class="input-btn" onclick="document.getElementById('fileInput').click()" title="Fichier"><i class="fas fa-paperclip"></i></button>
|
||
<button class="input-btn" onclick="document.getElementById('imageInput').click()" title="Image"><i class="fas fa-image"></i></button>
|
||
<input type="file" id="fileInput" style="display:none" multiple accept=".pdf,.doc,.docx,.xls,.xlsx,.txt" onchange="handleFiles(this.files)">
|
||
<input type="file" id="imageInput" style="display:none" multiple accept="image/*,video/*" onchange="handleFiles(this.files)">
|
||
<textarea id="input" placeholder="Écrivez votre message..." rows="1" onkeydown="if(event.key==='Enter'&&!event.shiftKey){event.preventDefault();send()}"></textarea>
|
||
<button class="send-btn" onclick="send()"><i class="fas fa-arrow-up"></i></button>
|
||
</div></div></div>
|
||
<div id="artPanel"><div class="art-header"><h3><i class="fas fa-file-alt"></i> <span id="artTitle">Document</span></h3><button class="art-close" onclick="closeArt()">×</button></div><div id="artContent"></div><div class="art-footer"><a id="artDL" href="#" class="btn" download><i class="fas fa-download"></i> Télécharger</a></div></div>
|
||
</div>
|
||
<div class="modal" id="helpModal"><div class="modal-content"><h3>🧞 Aide HAMID</h3><p><strong>Génération :</strong></p><ul><li>PDF - "Génère un PDF"</li><li>Word - "Génère un document Word"</li><li>Excel - "Génère un fichier Excel"</li><li>PPT - "Génère une présentation"</li><li>QR - "Génère un QR code"</li></ul><p>📎 Fichiers | 🖼️ Images</p><button onclick="document.getElementById('helpModal').classList.remove('show')">OK</button></div></div>
|
||
<script>
|
||
let prov='<?= $defaultProvider ?>';let hist=[];let files=[];
|
||
document.addEventListener('DOMContentLoaded',()=>{const o=document.querySelector('[data-prov="'+prov+'"]');if(o)o.classList.add('active')});
|
||
function esc(s){const d=document.createElement('div');d.textContent=s;return d.innerHTML}
|
||
function fmt(s){return s.replace(/\*\*([^*]+)\*\*/g,'<strong>$1</strong>').replace(/\[([^\]]+)\]\(([^)]+)\)/g,'<a href="$2" target="_blank">$1</a>').replace(/\n/g,'<br>')}
|
||
function selProv(p,n){prov=p;document.getElementById('currentProvider').textContent=n;document.querySelectorAll('.provider-option').forEach(e=>e.classList.remove('active'));const o=document.querySelector('[data-prov="'+p+'"]');if(o)o.classList.add('active');document.getElementById('providerMenu').classList.remove('show')}
|
||
function showHelp(){document.getElementById('helpModal').classList.add('show')}
|
||
function newChat(){hist=[];files=[];document.getElementById('msgs').innerHTML='<div class="welcome" id="welcome"><div class="welcome-icon">🧞</div><h2>Bonjour</h2><p>Assistant IA WEVADS</p><div class="quick-actions"><button class="quick-btn" onclick="sendQuick(\'Génère un PDF\')"><i class="fas fa-file-pdf" style="color:#ef4444"></i> PDF</button><button class="quick-btn" onclick="sendQuick(\'Génère un Word\')"><i class="fas fa-file-word" style="color:#2563eb"></i> Word</button><button class="quick-btn" onclick="sendQuick(\'Génère un Excel\')"><i class="fas fa-file-excel" style="color:#16a34a"></i> Excel</button></div></div>';closeArt()}
|
||
function sendQuick(m){document.getElementById('input').value=m;send()}
|
||
function handleFiles(f){for(let x of f)files.push(x)}
|
||
function addMsg(role,txt,meta={}){const w=document.getElementById('welcome');if(w)w.style.display='none';const d=document.createElement('div');d.className='msg msg-'+role;if(role==='user')d.innerHTML='<div class="bubble">'+esc(txt)+'</div>';else{let tags='<span class="tag prov">'+(meta.provider||prov.toUpperCase())+'</span>';if(meta.kb_used)tags+='<span class="tag kb">📚 KB</span>';if(meta.duration)tags+='<span class="tag">'+meta.duration+'ms</span>';d.innerHTML='<div class="avatar">🧞</div><div class="msg-wrap"><div class="msg-content">'+fmt(txt)+'</div><div class="msg-footer">'+tags+'</div></div>'}document.getElementById('msgs').appendChild(d);document.getElementById('msgs').scrollTop=9999}
|
||
async function send(){
|
||
const inp=document.getElementById('input');const m=inp.value.trim();if(!m)return;inp.value='';
|
||
addMsg('user',m);hist.push({role:'user',content:m});
|
||
document.getElementById('typing').classList.add('show');
|
||
try{
|
||
const fd=new FormData();fd.append('message',m);fd.append('provider',prov);fd.append('history',JSON.stringify(hist.slice(-6)));files.forEach(f=>fd.append('files[]',f));
|
||
const r=await fetch('/api/widget-api.php',{method:'POST',body:fd});const d=await r.json();
|
||
document.getElementById('typing').classList.remove('show');
|
||
if(d.success){addMsg('assistant',d.response,{provider:d.provider,duration:d.duration_ms,kb_used:d.kb_used});hist.push({role:'assistant',content:d.response});if(d.artifacts&&d.artifacts.length>0)showArt(d.artifacts[0])}
|
||
else addMsg('assistant','❌ '+(d.error||'Erreur'))
|
||
}catch(e){document.getElementById('typing').classList.remove('show');addMsg('assistant','❌ '+e.message)}
|
||
files=[]
|
||
}
|
||
function showArt(a){document.getElementById('artTitle').textContent=a.title||'Document';document.getElementById('artDL').href=a.url;const c=document.getElementById('artContent');if(a.type==='pdf')c.innerHTML='<iframe src="'+a.url+'"></iframe>';else if(a.type==='image')c.innerHTML='<div style="display:flex;align-items:center;justify-content:center;height:100%;padding:1rem"><img src="'+a.url+'" style="max-width:100%;max-height:100%"></div>';else c.innerHTML='<div style="text-align:center;padding:3rem"><i class="fas fa-file-alt" style="font-size:4rem;color:#06b6d4"></i><h3 style="margin:1rem 0">'+a.file+'</h3><a href="'+a.url+'" class="btn" download>Télécharger</a></div>';document.getElementById('artPanel').classList.add('open')}
|
||
function closeArt(){document.getElementById('artPanel').classList.remove('open')}
|
||
document.addEventListener('click',e=>{if(!e.target.closest('.provider-select'))document.getElementById('providerMenu').classList.remove('show');if(e.target.classList.contains('modal'))e.target.classList.remove('show')});
|
||
|
||
// === TOOLS FUNCTIONS ===
|
||
function toggleTools() {
|
||
const panel = document.getElementById("toolsPanel");
|
||
panel.style.display = panel.style.display === "none" ? "block" : "none";
|
||
}
|
||
|
||
function sendQuick(text) {
|
||
document.getElementById("messageInput").value = text;
|
||
document.getElementById("messageInput").focus();
|
||
}
|
||
|
||
async function runTool(action, params = {}) {
|
||
const url = new URL("/commonia/hamid-tools.php", window.location.origin);
|
||
url.searchParams.set("action", action);
|
||
for (const [k, v] of Object.entries(params)) {
|
||
url.searchParams.set(k, v);
|
||
}
|
||
|
||
try {
|
||
addMessage("assistant", `🔧 Exécution de ${action}...`);
|
||
const res = await fetch(url);
|
||
const data = await res.json();
|
||
|
||
let resultHTML = `<div class="tool-result"><div class="tool-header">🔧 ${action}</div><pre>${JSON.stringify(data, null, 2)}</pre></div>`;
|
||
addMessage("assistant", resultHTML, true);
|
||
} catch (e) {
|
||
addMessage("assistant", `❌ Erreur: ${e.message}`);
|
||
}
|
||
}
|
||
|
||
function promptTool(action, label, param, defaultVal = "") {
|
||
const value = prompt(label, defaultVal);
|
||
if (value) {
|
||
runTool(action, { [param]: value });
|
||
}
|
||
}
|
||
|
||
function addMessage(role, content, isHTML = false) {
|
||
const container = document.getElementById("messagesContainer") || document.querySelector(".messages-container");
|
||
if (!container) return;
|
||
|
||
const msg = document.createElement("div");
|
||
msg.className = "message " + role;
|
||
if (isHTML) {
|
||
msg.innerHTML = content;
|
||
} else {
|
||
msg.textContent = content;
|
||
}
|
||
container.appendChild(msg);
|
||
container.scrollTop = container.scrollHeight;
|
||
}
|
||
|
||
</script>
|
||
</body></html>
|
||
|
||
<!-- Tools Panel Modal -->
|
||
<div id="toolsPanelModal" style="display:none;position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.8);z-index:9999;padding:2rem;overflow-y:auto">
|
||
<div style="max-width:800px;margin:0 auto;background:#1e293b;border-radius:16px;padding:1.5rem;border:1px solid #334155">
|
||
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:1rem">
|
||
<h2 style="color:#06b6d4;margin:0">🔧 Tools Système HAMID</h2>
|
||
<button onclick="toggleToolsPanel()" style="background:none;border:none;color:#94a3b8;font-size:1.5rem;cursor:pointer">✕</button>
|
||
</div>
|
||
<div style="display:grid;grid-template-columns:repeat(4,1fr);gap:0.75rem;margin-bottom:1rem">
|
||
<button onclick="runTool('status')" class="tool-btn-modal">📊 Status</button>
|
||
<button onclick="runTool('tables')" class="tool-btn-modal">🗄️ Tables DB</button>
|
||
<button onclick="promptAndRun('list','Chemin:','/opt/wevads/public')" class="tool-btn-modal">📁 Fichiers</button>
|
||
<button onclick="promptAndRun('dns','Domaine:')" class="tool-btn-modal">📧 DNS</button>
|
||
<button onclick="promptAndRun('bash','Commande:')" class="tool-btn-modal">💻 Bash</button>
|
||
<button onclick="promptAndRun('sql','Requête SQL:')" class="tool-btn-modal">🔎 SQL</button>
|
||
<button onclick="promptAndRun('read','Chemin fichier:')" class="tool-btn-modal">📄 Lire</button>
|
||
<button onclick="promptAndRun('calc','Expression:')" class="tool-btn-modal">🧮 Calcul</button>
|
||
</div>
|
||
<div id="toolResultArea" style="background:#0f172a;border-radius:8px;padding:1rem;min-height:200px;max-height:400px;overflow-y:auto">
|
||
<div style="color:#64748b;text-align:center">Cliquez sur un tool pour l'exécuter</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<style>
|
||
.tool-btn-modal{display:flex;flex-direction:column;align-items:center;gap:0.25rem;padding:0.75rem;background:linear-gradient(135deg,#0f172a,#1e293b);border:1px solid #334155;border-radius:8px;color:#e2e8f0;cursor:pointer;font-size:0.85rem;transition:all 0.2s}
|
||
.tool-btn-modal:hover{border-color:#06b6d4;transform:translateY(-2px);background:linear-gradient(135deg,#1e3a5f,#0f172a)}
|
||
</style>
|
||
|
||
<script>
|
||
function toggleToolsPanel(){
|
||
const p=document.getElementById('toolsPanelModal');
|
||
p.style.display=p.style.display==='none'?'flex':'none';
|
||
}
|
||
|
||
async function runTool(action,params={}){
|
||
const area=document.getElementById('toolResultArea');
|
||
area.innerHTML='<div style="color:#06b6d4">⏳ Exécution de '+action+'...</div>';
|
||
|
||
const url=new URL('/commonia/hamid-tools.php',location.origin);
|
||
url.searchParams.set('action',action);
|
||
for(const[k,v]of Object.entries(params))url.searchParams.set(k,v);
|
||
|
||
try{
|
||
const res=await fetch(url);
|
||
const data=await res.json();
|
||
area.innerHTML='<div style="color:#06b6d4;font-weight:bold;margin-bottom:0.5rem">🔧 '+action+'</div><pre style="color:#10b981;white-space:pre-wrap;margin:0">'+JSON.stringify(data,null,2)+'</pre>';
|
||
}catch(e){
|
||
area.innerHTML='<div style="color:#ef4444">❌ Erreur: '+e.message+'</div>';
|
||
}
|
||
}
|
||
|
||
function promptAndRun(action,label,defaultVal=''){
|
||
const val=prompt(label,defaultVal);
|
||
if(val){
|
||
const paramMap={list:'path',dns:'domain',bash:'cmd',sql:'sql',read:'path',calc:'expr',search:'q',fetch:'url'};
|
||
runTool(action,{[paramMap[action]||'q']:val});
|
||
}
|
||
}
|
||
</script>
|