Files
wevads-platform/public/hamid-cli.php
2026-02-26 04:53:11 +01:00

515 lines
28 KiB
PHP

<?php
// === NOUVEAUX OUTILS HAMID ULTRA MAX++ ===
// OCR: /hamid-ocr.php
// YouTube: /hamid-youtube.php
// Email: /hamid-email.php
// Calendar: /hamid-calendar.php
// Scrape: /hamid-scrape.php
// History: /hamid-history.php
// Plugins: /hamid-plugins.php
// API: /hamid-api-public.php
require_once __DIR__ . "/hamid-providers-config.php"; ?>
<!DOCTYPE html>
<html data-theme="dark" lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>WEVAL MIND CLI - Superintelligence Terminal</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
:root {
--bg-primary: #0a0a0f;
--bg-secondary: #12121a;
--bg-tertiary: #1a1a2e;
--text-primary: #00ff00;
--text-secondary: #00d4ff;
--text-muted: #666;
--accent-cyan: #22d3ee;
--accent-purple: #a78bfa;
--accent-pink: #ff79c6;
--border-color: #333;
}
body { font-family: 'Fira Code', 'Consolas', 'Monaco', monospace; background: var(--bg-primary); color: var(--text-primary); height: 100vh; display: flex; flex-direction: column; overflow: hidden; }
/* Header */
.terminal-header { background: linear-gradient(135deg, var(--bg-secondary), var(--bg-tertiary)); padding: 12px 20px; display: flex; align-items: center; gap: 15px; border-bottom: 1px solid var(--border-color); }
.terminal-header .dots { display: flex; gap: 8px; }
.terminal-header .dot { width: 14px; height: 14px; border-radius: 50%; transition: all 0.3s; cursor: pointer; }
.terminal-header .dot:hover { transform: scale(1.2); }
.terminal-header .dot.red { background: #ff5f56; }
.terminal-header .dot.yellow { background: #ffbd2e; }
.terminal-header .dot.green { background: #27c93f; }
.terminal-header .title { flex: 1; text-align: center; color: var(--text-muted); font-size: 13px; }
.terminal-header .title span { color: var(--accent-cyan); font-weight: bold; }
.terminal-header select { background: var(--bg-tertiary); color: var(--text-primary); border: 1px solid var(--border-color); padding: 8px 12px; border-radius: 6px; font-family: inherit; font-size: 12px; cursor: pointer; }
.terminal-header select:hover { border-color: var(--accent-cyan); }
/* Stats Bar */
.stats-bar { background: var(--bg-secondary); padding: 8px 20px; display: flex; gap: 20px; border-bottom: 1px solid var(--border-color); font-size: 11px; color: var(--text-muted); }
.stats-bar .stat { display: flex; align-items: center; gap: 6px; }
.stats-bar .stat-value { color: var(--accent-cyan); font-weight: bold; }
.stats-bar .stat-icon { font-size: 14px; }
/* Main Terminal */
.terminal-container { flex: 1; display: flex; overflow: hidden; }
.sidebar { width: 250px; background: var(--bg-secondary); border-right: 1px solid var(--border-color); display: flex; flex-direction: column; }
.sidebar-header { padding: 15px; border-bottom: 1px solid var(--border-color); font-size: 12px; color: var(--accent-cyan); font-weight: bold; }
.sidebar-section { padding: 10px 15px; }
.sidebar-section h4 { color: var(--text-muted); font-size: 10px; text-transform: uppercase; margin-bottom: 8px; }
.sidebar-item { padding: 8px 12px; margin: 4px 0; border-radius: 6px; cursor: pointer; font-size: 12px; color: var(--text-secondary); transition: all 0.2s; display: flex; align-items: center; gap: 8px; }
.sidebar-item:hover { background: var(--bg-tertiary); color: var(--text-primary); }
.sidebar-item.active { background: var(--accent-cyan); color: var(--bg-primary); }
.history-list { flex: 1; overflow-y: auto; padding: 10px; }
.history-item { padding: 8px 10px; margin: 4px 0; border-radius: 4px; font-size: 11px; color: var(--text-muted); cursor: pointer; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.history-item:hover { background: var(--bg-tertiary); color: var(--text-secondary); }
/* Terminal Output */
.terminal-main { flex: 1; display: flex; flex-direction: column; }
.terminal { flex: 1; padding: 20px; overflow-y: auto; font-size: 14px; line-height: 1.8; }
.terminal::-webkit-scrollbar { width: 8px; }
.terminal::-webkit-scrollbar-track { background: var(--bg-secondary); }
.terminal::-webkit-scrollbar-thumb { background: var(--border-color); border-radius: 4px; }
.line { margin-bottom: 8px; white-space: pre-wrap; word-break: break-word; animation: fadeIn 0.3s ease; }
@keyframes fadeIn { from { opacity: 0; transform: translateY(5px); } to { opacity: 1; transform: translateY(0); } }
.line.input { color: var(--text-secondary); }
.line.output { color: var(--text-primary); }
.line.error { color: #ff5f56; }
.line.system { color: var(--text-muted); font-style: italic; }
.line.success { color: #27c93f; }
.line .prompt { color: var(--accent-pink); }
.line .user { color: var(--text-secondary); }
.line .time { color: var(--text-muted); font-size: 10px; margin-left: 10px; }
/* Thinking Box */
.thinking-box { background: linear-gradient(135deg, rgba(167,139,250,0.1), rgba(34,211,238,0.05)); border: 1px solid rgba(167,139,250,0.3); border-radius: 12px; margin: 10px 0; overflow: hidden; }
.thinking-header { display: flex; align-items: center; gap: 10px; padding: 12px 16px; cursor: pointer; color: var(--accent-purple); font-size: 13px; }
.thinking-header:hover { background: rgba(167,139,250,0.1); }
.thinking-header .sparkle { animation: sparkle 2s linear infinite; }
@keyframes sparkle { 0%, 100% { opacity: 0.5; transform: rotate(0deg); } 50% { opacity: 1; transform: rotate(180deg); } }
.thinking-header .chevron { margin-left: auto; transition: transform 0.3s; }
.thinking-box.expanded .chevron { transform: rotate(180deg); }
.thinking-content { max-height: 0; overflow: hidden; transition: max-height 0.4s ease; font-size: 12px; color: var(--text-muted); line-height: 1.6; }
.thinking-box.expanded .thinking-content { max-height: 300px; padding: 12px 16px; border-top: 1px solid rgba(167,139,250,0.2); overflow-y: auto; }
/* Code Blocks */
.code-block { background: var(--bg-tertiary); border: 1px solid var(--border-color); border-radius: 8px; margin: 10px 0; overflow: hidden; }
.code-header { display: flex; justify-content: space-between; align-items: center; padding: 8px 12px; background: var(--bg-secondary); border-bottom: 1px solid var(--border-color); font-size: 11px; color: var(--text-muted); }
.code-header .lang { color: var(--accent-cyan); }
.code-header .copy-btn { background: none; border: none; color: var(--text-muted); cursor: pointer; padding: 4px 8px; border-radius: 4px; }
.code-header .copy-btn:hover { background: var(--bg-tertiary); color: var(--text-primary); }
.code-content { padding: 12px; font-size: 13px; overflow-x: auto; }
.code-content pre { margin: 0; }
/* Input Line */
.input-area { background: var(--bg-secondary); border-top: 1px solid var(--border-color); padding: 15px 20px; }
.input-line { display: flex; align-items: center; background: var(--bg-tertiary); border: 1px solid var(--border-color); border-radius: 8px; padding: 12px 16px; transition: border-color 0.3s; }
.input-line:focus-within { border-color: var(--accent-cyan); box-shadow: 0 0 20px rgba(34,211,238,0.1); }
.input-line .prompt { color: var(--accent-pink); margin-right: 12px; font-weight: bold; }
.input-line input { flex: 1; background: transparent; border: none; color: var(--text-primary); font-family: inherit; font-size: 14px; outline: none; }
.input-line input::placeholder { color: var(--text-muted); }
.input-actions { display: flex; gap: 8px; margin-left: 12px; }
.input-actions button { background: var(--bg-secondary); border: 1px solid var(--border-color); color: var(--text-muted); padding: 6px 12px; border-radius: 6px; cursor: pointer; font-size: 12px; transition: all 0.2s; }
.input-actions button:hover { border-color: var(--accent-cyan); color: var(--accent-cyan); }
.input-actions button.primary { background: var(--accent-cyan); border-color: var(--accent-cyan); color: var(--bg-primary); }
.input-actions button.primary:hover { background: #06b6d4; }
/* Shortcuts */
.shortcuts { display: flex; gap: 15px; margin-top: 10px; font-size: 11px; color: var(--text-muted); }
.shortcut { display: flex; align-items: center; gap: 6px; }
.shortcut kbd { background: var(--bg-tertiary); padding: 2px 6px; border-radius: 4px; font-family: inherit; }
/* ASCII Art */
.ascii-art { color: var(--accent-cyan); font-size: 10px; line-height: 1.2; margin-bottom: 20px; opacity: 0.8; }
/* Loading Animation */
.loading { display: flex; align-items: center; gap: 8px; color: var(--text-muted); }
.loading-dots { display: flex; gap: 4px; }
.loading-dots span { width: 6px; height: 6px; background: var(--accent-cyan); border-radius: 50%; animation: bounce 1.4s infinite ease-in-out both; }
.loading-dots span:nth-child(1) { animation-delay: -0.32s; }
.loading-dots span:nth-child(2) { animation-delay: -0.16s; }
@keyframes bounce { 0%, 80%, 100% { transform: scale(0); } 40% { transform: scale(1); } }
/* Mobile */
@media (max-width: 768px) {
.sidebar { display: none; }
.stats-bar { flex-wrap: wrap; gap: 10px; }
}
</style>
</head>
<body>
<div class="terminal-header">
<div class="dots">
<div class="dot red" title="Fermer"></div>
<div class="dot yellow" title="Réduire"></div>
<div class="dot green" title="Agrandir"></div>
</div>
<div class="title">hamid@wevads:~ <span>WEVAL MIND CLI v3.0</span></div>
<?php
// === NOUVEAUX OUTILS HAMID ULTRA MAX++ ===
// OCR: /hamid-ocr.php
// YouTube: /hamid-youtube.php
// Email: /hamid-email.php
// Calendar: /hamid-calendar.php
// Scrape: /hamid-scrape.php
// History: /hamid-history.php
// Plugins: /hamid-plugins.php
// API: /hamid-api-public.php
echo hamid_providers_dropdown("cerebras", "provider", ""); ?>
</div>
<div class="stats-bar">
<div class="stat"><span class="stat-icon">🧠</span> Provider: <span class="stat-value" id="currentProvider">cerebras</span></div>
<div class="stat"><span class="stat-icon">📚</span> KB: <span class="stat-value">141 entries</span></div>
<div class="stat"><span class="stat-icon">⚡</span> Latence: <span class="stat-value" id="latency">--</span></div>
<div class="stat"><span class="stat-icon">💬</span> Session: <span class="stat-value" id="msgCount">0</span> msgs</div>
<div class="stat"><span class="stat-icon">🕐</span> <span class="stat-value" id="clock">--:--:--</span></div>
</div>
<div class="terminal-container">
<div class="sidebar">
<div class="sidebar-header">📁 NAVIGATION</div>
<div class="sidebar-section">
<h4>Commandes Rapides</h4>
<div class="sidebar-item" onclick="quickCmd('help')">📖 Aide</div>
<div class="sidebar-item" onclick="quickCmd('status')">📊 Status</div>
<div class="sidebar-item" onclick="quickCmd('providers')">🔌 Providers</div>
<div class="sidebar-item" onclick="quickCmd('kb search')">🔍 Recherche KB</div>
<div class="sidebar-item" onclick="quickCmd('clear')">🧹 Clear</div>
</div>
<div class="sidebar-section">
<h4>Actions</h4>
<div class="sidebar-item" onclick="exportHistory()">💾 Exporter</div>
<div class="sidebar-item" onclick="toggleTheme()">🎨 Thème</div>
<div class="sidebar-item" onclick="openFullscreen()">🖥️ Fullscreen</div>
</div>
<div class="sidebar-section">
<h4>Historique</h4>
</div>
<div class="history-list" id="historyList"></div>
</div>
<div class="terminal-main">
<div class="terminal" id="terminal">
<pre class="ascii-art">
██╗███████╗██╗ ██╗ █████╗ ██╗ ███╗ ███╗██╗███╗ ██╗██████╗
██║██╔════╝██║ ██║██╔══██╗██║ ████╗ ████║██║████╗ ██║██╔══██╗
█╗ ██║█████╗ ██║ ██║███████║██║ ██╔████╔██║██║██╔██╗ ██║██║ ██║
╚██╗ ██╔╝██╔══██║██║ ██║╚██╔╝██║██║██║╚██╗██║██║ ██║
╚████╔╝ ██║ ██║███████╗ ██║ ╚═╝ ██║██║██║ ╚████║██████╔╝
╚══╝╚══╝ ╚══════╝ ╚═══╝ ╚═╝ ╚═╝╚══════╝ ╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝╚═════╝
CLI v3.0 - Superintelligence Terminal Interface
</pre>
<div class="line system">Bienvenue dans WEVAL MIND CLI - Votre interface terminal IA avancée</div>
<div class="line system">Tapez 'help' pour la liste des commandes ou posez directement une question.</div>
<div class="line system">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</div>
</div>
<div class="input-area">
<div class="input-line">
<span class="prompt">hamid@wevads:~$</span>
<input type="text" id="input" placeholder="Entrez une commande ou une question..." autofocus autocomplete="off">
<div class="input-actions">
<button onclick="clearTerminal()">Clear</button>
<button class="primary" onclick="execute()">Envoyer ⏎</button>
</div>
</div>
<div class="shortcuts">
<div class="shortcut"><kbd>↑↓</kbd> Historique</div>
<div class="shortcut"><kbd>Tab</kbd> Autocomplete</div>
<div class="shortcut"><kbd>Ctrl+L</kbd> Clear</div>
<div class="shortcut"><kbd>Ctrl+K</kbd> Recherche KB</div>
</div>
</div>
</div>
</div>
<script>
const terminal = document.getElementById('terminal');
const input = document.getElementById('input');
const providerSelect = document.getElementById('provider');
const historyList = document.getElementById('historyList');
let sessionId = 'cli_' + Date.now();
let history = [];
let historyIndex = -1;
let messageCount = 0;
let isDarkTheme = true;
// Clock
setInterval(() => {
document.getElementById('clock').textContent = new Date().toLocaleTimeString('fr-FR');
}, 1000);
// Provider change
providerSelect.onchange = () => {
document.getElementById('currentProvider').textContent = providerSelect.value;
addLine(`⚡ Provider changé: ${providerSelect.value}`, 'system');
};
// Input events
input.addEventListener('keydown', e => {
if (e.key === 'Enter') { execute(); }
else if (e.key === 'ArrowUp') { navigateHistory(1); e.preventDefault(); }
else if (e.key === 'ArrowDown') { navigateHistory(-1); e.preventDefault(); }
else if (e.key === 'Tab') { autocomplete(); e.preventDefault(); }
else if (e.ctrlKey && e.key === 'l') { clearTerminal(); e.preventDefault(); }
else if (e.ctrlKey && e.key === 'k') { input.value = 'kb search '; e.preventDefault(); }
});
function navigateHistory(dir) {
if (history.length === 0) return;
historyIndex = Math.max(-1, Math.min(history.length - 1, historyIndex + dir));
input.value = historyIndex >= 0 ? history[history.length - 1 - historyIndex] : '';
}
function autocomplete() {
const cmds = ['help', 'clear', 'status', 'providers', 'kb search', 'kb add', 'export', 'theme', 'history'];
const val = input.value.toLowerCase();
const match = cmds.find(c => c.startsWith(val));
if (match) input.value = match;
}
function addLine(text, type = 'output') {
const div = document.createElement('div');
div.className = 'line ' + type;
// Format code blocks
if (text.includes('```')) {
div.innerHTML = formatCodeBlocks(text);
} else {
div.innerHTML = formatText(text);
}
terminal.appendChild(div);
terminal.scrollTop = terminal.scrollHeight;
}
function formatText(text) {
return text
.replace(/\*\*(.*?)\*\*/g, '<strong style="color:#22d3ee">$1</strong>')
.replace(/`([^`]+)`/g, '<code style="background:#1a1a2e;padding:2px 6px;border-radius:4px">$1</code>')
.replace(/\n/g, '<br>');
}
function formatCodeBlocks(text) {
return text.replace(/```(\w+)?\n?([\s\S]*?)```/g, (_, lang, code) => {
return `<div class="code-block">
<div class="code-header">
<span class="lang">${lang || 'code'}</span>
<button class="copy-btn" onclick="copyCode(this)">📋 Copier</button>
</div>
<div class="code-content"><pre>${code.trim()}</pre></div>
</div>`;
});
}
function copyCode(btn) {
const code = btn.closest('.code-block').querySelector('pre').textContent;
navigator.clipboard.writeText(code);
btn.textContent = '✅ Copié!';
setTimeout(() => btn.textContent = '📋 Copier', 2000);
}
function addThinking(text) {
const div = document.createElement('div');
div.className = 'thinking-box';
div.innerHTML = `
<div class="thinking-header" onclick="this.parentElement.classList.toggle('expanded')">
<span class="sparkle">✨</span>
<span>Réflexion de l'IA</span>
<span class="chevron">▼</span>
</div>
<div class="thinking-content">${text}</div>
`;
terminal.appendChild(div);
}
function addLoading() {
const div = document.createElement('div');
div.className = 'line loading';
div.id = 'loading';
div.innerHTML = `<span>Traitement en cours</span><div class="loading-dots"><span></span><span></span><span></span></div>`;
terminal.appendChild(div);
terminal.scrollTop = terminal.scrollHeight;
}
function removeLoading() {
const el = document.getElementById('loading');
if (el) el.remove();
}
function execute() {
const cmd = input.value.trim();
if (!cmd) return;
history.push(cmd);
historyIndex = -1;
updateHistoryList();
const time = new Date().toLocaleTimeString('fr-FR');
addLine(`<span class="prompt">hamid@wevads:~$</span> <span class="user">${cmd}</span> <span class="time">${time}</span>`, 'input');
input.value = '';
// Built-in commands
if (cmd === 'help') { showHelp(); return; }
if (cmd === 'clear') { clearTerminal(); return; }
if (cmd === 'providers') { showProviders(); return; }
if (cmd === 'status') { showStatus(); return; }
if (cmd === 'history') { showHistory(); return; }
if (cmd === 'export') { exportHistory(); return; }
if (cmd === 'theme') { toggleTheme(); return; }
if (cmd.startsWith('kb search ')) { searchKB(cmd.substring(10)); return; }
// Send to AI
sendToAI(cmd);
}
function showHelp() {
addLine('╔══════════════════════════════════════════════════════════════════╗', 'system');
addLine('║ WEVAL MIND CLI - AIDE ║', 'system');
addLine('╠══════════════════════════════════════════════════════════════════╣', 'system');
addLine('║ COMMANDES SYSTÈME ║', 'system');
addLine('║ help Affiche cette aide ║', 'system');
addLine('║ clear Efface le terminal ║', 'system');
addLine('║ status Affiche état du système ║', 'system');
addLine('║ providers Liste les providers IA ║', 'system');
addLine('║ history Affiche historique ║', 'system');
addLine('║ export Exporte la conversation ║', 'system');
addLine('║ theme Change le thème ║', 'system');
addLine('╠══════════════════════════════════════════════════════════════════╣', 'system');
addLine('║ KNOWLEDGE BASE ║', 'system');
addLine('║ kb search [terme] Recherche dans la KB ║', 'system');
addLine('╠══════════════════════════════════════════════════════════════════╣', 'system');
addLine('║ RACCOURCIS: ↑↓ Historique | Tab Auto | Ctrl+L Clear ║', 'system');
addLine('╚══════════════════════════════════════════════════════════════════╝', 'system');
}
function showStatus() {
addLine(`
Provider: ${providerSelect.value}
Session ID: ${sessionId}
Messages: ${messageCount}
KB Entries: 141
Uptime: ${Math.floor((Date.now() - parseInt(sessionId.split('_')[1])) / 1000)}s
Thème: ${isDarkTheme ? 'Sombre' : 'Clair'}`, 'system');
}
function showHistory() {
if (history.length === 0) {
addLine('Historique vide.', 'system');
return;
}
addLine('📜 HISTORIQUE DES COMMANDES\n━━━━━━━━━━━━━━━━━━━━━━━━━━━', 'system');
history.forEach((cmd, i) => addLine(` ${i + 1}. ${cmd}`, 'system'));
}
function clearTerminal() {
terminal.innerHTML = '';
addLine('Terminal effacé.', 'system');
}
function toggleTheme() {
isDarkTheme = !isDarkTheme;
document.body.style.background = isDarkTheme ? '#0a0a0f' : '#f5f5f5';
addLine(`🎨 Thème changé: ${isDarkTheme ? 'Sombre' : 'Clair'}`, 'system');
}
function exportHistory() {
const content = history.join('\n');
const blob = new Blob([content], { type: 'text/plain' });
const a = document.createElement('a');
a.href = URL.createObjectURL(blob);
a.download = `weval-cli-history-${Date.now()}.txt`;
a.click();
addLine('💾 Historique exporté!', 'success');
}
function updateHistoryList() {
historyList.innerHTML = history.slice(-10).reverse().map(cmd =>
`<div class="history-item" onclick="input.value='${cmd}'">${cmd}</div>`
).join('');
}
function quickCmd(cmd) {
input.value = cmd;
if (cmd !== 'kb search') execute();
}
function openFullscreen() {
window.open('/hamid-fullscreen.php', '_blank');
}
async function searchKB(term) {
addLoading();
try {
const res = await fetch('/hamid-api.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ action: 'search_kb', query: term })
});
const data = await res.json();
removeLoading();
if (data.results && data.results.length > 0) {
addLine(`🔍 Résultats KB pour "${term}":\n━━━━━━━━━━━━━━━━━━━━━━━━`, 'system');
data.results.forEach((r, i) => addLine(`${i + 1}. ${r.title}\n ${r.content.substring(0, 100)}...`, 'output'));
} else {
addLine(`Aucun résultat pour "${term}"`, 'system');
}
} catch (e) {
removeLoading();
addLine('Erreur recherche KB: ' + e.message, 'error');
}
}
async function sendToAI(message) {
addLoading();
const startTime = Date.now();
try {
const res = await fetch('/hamid-api.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
message: message,
provider: providerSelect.value,
session_id: sessionId
})
});
const data = await res.json();
removeLoading();
const latency = Date.now() - startTime;
document.getElementById('latency').textContent = latency + 'ms';
messageCount++;
document.getElementById('msgCount').textContent = messageCount;
if (data.error) {
addLine('❌ ' + data.error, 'error');
} else {
// Show thinking if available
if (data.thinking) {
addThinking(data.thinking);
}
let resp = data.response.replace(/<thinking>[\s\S]*?<\/thinking>/gi, "").trim(); addLine(resp);
addLine(`[${data.provider || providerSelect.value} | ${data.duration || latency}ms | KB:${data.kb_count || 0}]`, 'system');
if (data.generated_doc) {
addLine(`📄 Document généré: ${data.generated_doc.url}`, 'success');
}
}
} catch (e) {
removeLoading();
addLine('❌ Erreur: ' + e.message, 'error');
}
}
</script>
</body>
</html>