Spaces:
Runtime error
Runtime error
| import chalk from 'chalk'; | |
| import inquirer from 'inquirer'; | |
| import ora from 'ora'; | |
| import fs from 'fs'; | |
| import path from 'path'; | |
| import os from 'os'; | |
| import { execSync } from 'child_process'; | |
| import { marked } from 'marked'; | |
| import TerminalRenderer from 'marked-terminal'; | |
| const theme = { | |
| agent: chalk.hex('#00FFAA'), | |
| user: chalk.hex('#C792EA'), | |
| command: chalk.hex('#FFD700'), | |
| error: chalk.hex('#FF5555'), | |
| info: chalk.hex('#569CD6'), | |
| border: chalk.hex('#2A2A2A'), | |
| text: chalk.hex('#E0E0E0') | |
| }; | |
| // Configurer le rendu Markdown pour le terminal (styles chalk) | |
| marked.setOptions({ | |
| renderer: new TerminalRenderer({ | |
| code: theme.command, | |
| blockquote: theme.agent, | |
| html: theme.agent, | |
| heading: theme.info, | |
| firstHeading: theme.info, | |
| listitem: theme.agent, | |
| table: theme.agent, | |
| strong: theme.agent, | |
| em: theme.agent, | |
| link: theme.info, | |
| href: theme.info, | |
| unstyled: theme.agent, | |
| tab: 2 | |
| }) | |
| }); | |
| const AUTHOR = "DJAKOUA KWANKAM"; | |
| const APP_NAME = "Cypher Coder"; | |
| // Global Session State & Config | |
| let chatMessages = []; | |
| let lastUserInput = ""; | |
| let lastAssistantResponse = ""; | |
| let commandHistory = []; | |
| let savedContexts = {}; | |
| let loadedFiles = []; | |
| let macros = {}; | |
| let logs = []; | |
| const sessionConfig = { | |
| model: "Qwen/Qwen2.5-Coder-32B-Instruct", | |
| temperature: 0.7, | |
| top_p: 0.9, | |
| max_tokens: 2048, | |
| stream: false, | |
| sandbox: false, | |
| verbose: false, | |
| silent: false, | |
| color: true, | |
| theme: "dark", | |
| format: "md", | |
| lang: "fr", | |
| env: {} | |
| }; | |
| function addLog(level, message) { | |
| const logItem = `[${new Date().toISOString()}] [${level}] ${message}`; | |
| logs.push(logItem); | |
| } | |
| const BANNER = theme.info(` | |
| _____ _---------------+ | |
| / ____| | | ____ _ | | |
| | | _ _ _ __ | |__| _ \\| | | CYPHER CODER CLI | |
| | | | | | | '_ \\ | __ |_) | | | L'IA experte en dรฉveloppement local | |
| | |___| |_| | |_) || | | __/| |___ | Crรฉรฉ par ${AUTHOR} | |
| \\_____\\__, | .__/ |_| |_| |_____| | |
| __/ | | | |
| |___/|_| +-----------------------+ | |
| `); | |
| // ----------------------------------------------------- | |
| // Dรฉfinition des Outils Globaux (Capabilities) | |
| // ----------------------------------------------------- | |
| const tools = [ | |
| { | |
| type: "function", | |
| function: { | |
| name: "read_file", | |
| description: "Lit le contenu complet d'un fichier local sur la machine de l'utilisateur.", | |
| parameters: { | |
| type: "object", | |
| properties: { | |
| path: { type: "string", description: "Le chemin du fichier ร lire (relatif ou absolu)." } | |
| }, | |
| required: ["path"] | |
| } | |
| } | |
| }, | |
| { | |
| type: "function", | |
| function: { | |
| name: "write_file", | |
| description: "Crรฉe ou รฉcrase un fichier local avec un nouveau contenu.", | |
| parameters: { | |
| type: "object", | |
| properties: { | |
| path: { type: "string", description: "Le chemin du fichier ร รฉcrire." }, | |
| content: { type: "string", description: "Le contenu textuel ร รฉcrire dans le fichier." } | |
| }, | |
| required: ["path", "content"] | |
| } | |
| } | |
| }, | |
| { | |
| type: "function", | |
| function: { | |
| name: "patch_file", | |
| description: "Modifie de maniรจre ciblรฉe un bloc de texte unique dans un fichier existant (Search and Replace). Utile pour modifier des gros fichiers sans les rรฉรฉcrire complรจtement.", | |
| parameters: { | |
| type: "object", | |
| properties: { | |
| path: { type: "string", description: "Le chemin du fichier ร modifier." }, | |
| search: { type: "string", description: "Le bloc exact de code ร remplacer (doit รชtre unique dans le fichier)." }, | |
| replace: { type: "string", description: "Le nouveau bloc de code qui le remplace." } | |
| }, | |
| required: ["path", "search", "replace"] | |
| } | |
| } | |
| }, | |
| { | |
| type: "function", | |
| function: { | |
| name: "list_dir", | |
| description: "Liste les fichiers et dossiers dans un rรฉpertoire local. Peut รชtre rรฉcursif.", | |
| parameters: { | |
| type: "object", | |
| properties: { | |
| path: { type: "string", description: "Le chemin du dossier ร lister (par dรฉfaut '.')." }, | |
| recursive: { type: "boolean", description: "Si vrai, liste les sous-dossiers de maniรจre rรฉcursive." } | |
| }, | |
| required: ["path"] | |
| } | |
| } | |
| }, | |
| { | |
| type: "function", | |
| function: { | |
| name: "find_files", | |
| description: "Recherche des fichiers rรฉcursivement par nom en utilisant un motif joker (ex: '*.js', 'package.json'). Permet de repรฉrer rapidement des fichiers dans des sous-dossiers.", | |
| parameters: { | |
| type: "object", | |
| properties: { | |
| pattern: { type: "string", description: "Le motif de recherche (ex: '*.py', '*test*')." }, | |
| path: { type: "string", description: "Le chemin de dรฉpart pour la recherche (par dรฉfaut '.')." } | |
| }, | |
| required: ["pattern"] | |
| } | |
| } | |
| }, | |
| { | |
| type: "function", | |
| function: { | |
| name: "grep_search", | |
| description: "Recherche textuelle rรฉcursive dans tous les fichiers d'un dossier pour trouver les occurrences d'une chaรฎne de caractรจres spรฉcifique (similaire ร ripgrep).", | |
| parameters: { | |
| type: "object", | |
| properties: { | |
| query: { type: "string", description: "La chaรฎne de caractรจres ou le mot-clรฉ ร rechercher dans les fichiers." }, | |
| path: { type: "string", description: "Le chemin de dรฉpart pour la recherche (par dรฉfaut '.')." } | |
| }, | |
| required: ["query"] | |
| } | |
| } | |
| }, | |
| { | |
| type: "function", | |
| function: { | |
| name: "run_command", | |
| description: "Exรฉcute une commande systรจme ou shell dans le terminal local de l'utilisateur.", | |
| parameters: { | |
| type: "object", | |
| properties: { | |
| command: { type: "string", description: "La commande shell ร exรฉcuter." } | |
| }, | |
| required: ["command"] | |
| } | |
| } | |
| } | |
| ]; | |
| // Outil d'exรฉcution d'API robuste via curl pour contourner les problรจmes de socket de Node.js | |
| function callApiViaCurl(messages, clientTools) { | |
| const payload = JSON.stringify({ | |
| messages, | |
| tools: clientTools, | |
| model: sessionConfig.model, | |
| temperature: sessionConfig.temperature, | |
| top_p: sessionConfig.top_p, | |
| max_tokens: sessionConfig.max_tokens, | |
| username: os.userInfo().username || "local-user" | |
| }); | |
| const escapedPayload = payload.replace(/'/g, "'\\''"); | |
| const command = `curl -s -X POST -H "Content-Type: application/json" -d '${escapedPayload}' https://theshellmaster-cypher-coder.hf.space/api/chat`; | |
| addLog("DEBUG", `Envoi payload API vers HF Space: modรจle=${sessionConfig.model}, tempรฉrature=${sessionConfig.temperature}`); | |
| const output = execSync(command).toString(); | |
| try { | |
| const responseJson = JSON.parse(output); | |
| if (responseJson.error) { | |
| throw new Error(responseJson.error); | |
| } | |
| return responseJson.message; | |
| } catch (e) { | |
| throw new Error(`Erreur de connexion avec le serveur Cypher: ${e.message}\nRรฉponse brute: ${output}`); | |
| } | |
| } | |
| // ----------------------------------------------------- | |
| // Implรฉmentation algorithmique des rรฉsolveurs d'outils | |
| // ----------------------------------------------------- | |
| // Helper de listing rรฉcursif propre | |
| function listFilesRecursive(dir, maxDepth = 3, currentDepth = 1) { | |
| let results = []; | |
| try { | |
| const list = fs.readdirSync(dir); | |
| for (const file of list) { | |
| const filePath = path.join(dir, file); | |
| const stat = fs.statSync(filePath); | |
| const relativePath = path.relative(".", filePath); | |
| // Ignorer les dossiers indรฉsirables | |
| if (file === 'node_modules' || file === '.git' || file === '.venv' || file === 'env' || file === '.cache' || file === 'package-lock.json') { | |
| continue; | |
| } | |
| if (stat.isDirectory()) { | |
| results.push({ path: relativePath, type: 'dossier' }); | |
| if (currentDepth < maxDepth) { | |
| results = results.concat(listFilesRecursive(filePath, maxDepth, currentDepth + 1)); | |
| } | |
| } else { | |
| results.push({ path: relativePath, type: 'fichier', sizeBytes: stat.size }); | |
| } | |
| } | |
| } catch (e) { | |
| // Ignorer les dossiers inaccessibles | |
| } | |
| return results; | |
| } | |
| // Rรฉsolveurs locaux pour les outils systรจme | |
| async function handleToolExecution(name, args) { | |
| const resolvedPath = path.resolve(args.path || "."); | |
| switch (name) { | |
| case 'read_file': | |
| try { | |
| const targetPath = path.resolve(args.path); | |
| if (!fs.existsSync(targetPath)) { | |
| return `Erreur: Le fichier n'existe pas ร l'emplacement ${targetPath}`; | |
| } | |
| const content = fs.readFileSync(targetPath, 'utf8'); | |
| return content; | |
| } catch (err) { | |
| return `Erreur lors de la lecture du fichier: ${err.message}`; | |
| } | |
| case 'write_file': | |
| try { | |
| const targetPath = path.resolve(args.path); | |
| console.log(theme.info(`\nCypher Coder veut modifier/crรฉer le fichier : ${chalk.cyan(targetPath)}`)); | |
| const { confirmWrite } = await inquirer.prompt([ | |
| { | |
| type: 'confirm', | |
| name: 'confirmWrite', | |
| message: 'Autoriser la crรฉation ou modification de ce fichier ?', | |
| default: true | |
| } | |
| ]); | |
| if (!confirmWrite) { | |
| return "Action refusรฉe par l'utilisateur."; | |
| } | |
| const dir = path.dirname(targetPath); | |
| if (!fs.existsSync(dir)) { | |
| fs.mkdirSync(dir, { recursive: true }); | |
| } | |
| fs.writeFileSync(targetPath, args.content, 'utf8'); | |
| console.log(chalk.green(`โ Fichier enregistrรฉ avec succรจs.`)); | |
| return `Fichier รฉcrit avec succรจs ร l'emplacement ${targetPath}`; | |
| } catch (err) { | |
| return `Erreur lors de l'รฉcriture du fichier: ${err.message}`; | |
| } | |
| case 'patch_file': | |
| try { | |
| const targetPath = path.resolve(args.path); | |
| console.log(theme.info(`\nCypher Coder veut modifier un bloc de code dans : ${chalk.cyan(targetPath)}`)); | |
| console.log(chalk.dim("--- BLOC ร RECHERCHER ---")); | |
| console.log(chalk.red(args.search)); | |
| console.log(chalk.dim("--- NOUVEAU BLOC ---")); | |
| console.log(chalk.green(args.replace)); | |
| console.log(chalk.dim("------------------------")); | |
| const { confirmPatch } = await inquirer.prompt([ | |
| { | |
| type: 'confirm', | |
| name: 'confirmPatch', | |
| message: 'Autoriser ce remplacement ciblรฉ ?', | |
| default: true | |
| } | |
| ]); | |
| if (!confirmPatch) { | |
| return "Action refusรฉe par l'utilisateur."; | |
| } | |
| if (!fs.existsSync(targetPath)) { | |
| return `Erreur: Le fichier ${targetPath} n'existe pas.`; | |
| } | |
| const content = fs.readFileSync(targetPath, 'utf8'); | |
| const occurrences = content.split(args.search).length - 1; | |
| if (occurrences === 0) { | |
| return `Erreur: Le bloc de texte ร remplacer n'a pas รฉtรฉ trouvรฉ. Assure-toi que les espaces et la mise en page correspondent exactement.`; | |
| } | |
| if (occurrences > 1) { | |
| return `Erreur: Le bloc ร remplacer apparaรฎt ${occurrences} fois dans le fichier. Rends la recherche plus spรฉcifique en englobant d'autres lignes.`; | |
| } | |
| const newContent = content.replace(args.search, args.replace); | |
| fs.writeFileSync(targetPath, newContent, 'utf8'); | |
| console.log(chalk.green(`โ Remplacement appliquรฉ avec succรจs.`)); | |
| return "Remplacement appliquรฉ avec succรจs de maniรจre unique."; | |
| } catch (err) { | |
| return `Erreur lors du remplacement: ${err.message}`; | |
| } | |
| case 'list_dir': | |
| try { | |
| const targetPath = path.resolve(args.path || "."); | |
| if (!fs.existsSync(targetPath)) { | |
| return `Erreur: Le dossier n'existe pas ร l'emplacement ${targetPath}`; | |
| } | |
| if (args.recursive) { | |
| const files = listFilesRecursive(targetPath, 3, 1); | |
| return JSON.stringify(files, null, 2); | |
| } else { | |
| const items = fs.readdirSync(targetPath); | |
| const list = items.map(item => { | |
| const itemPath = path.join(targetPath, item); | |
| const itemStats = fs.statSync(itemPath); | |
| return { | |
| name: item, | |
| type: itemStats.isDirectory() ? 'dossier' : 'fichier', | |
| sizeBytes: itemStats.size | |
| }; | |
| }); | |
| return JSON.stringify(list, null, 2); | |
| } | |
| } catch (err) { | |
| return `Erreur lors de la liste du dossier: ${err.message}`; | |
| } | |
| case 'find_files': | |
| try { | |
| const startDir = path.resolve(args.path || "."); | |
| const escapedPattern = args.pattern | |
| .replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&') | |
| .replace(/\\\*/g, '.*') | |
| .replace(/\\\?/g, '.'); | |
| const regex = new RegExp(`^${escapedPattern}$`, 'i'); | |
| const allFiles = listFilesRecursive(startDir, 5, 1); | |
| const matched = allFiles | |
| .filter(item => item.type === 'fichier' && regex.test(path.basename(item.path))) | |
| .map(item => item.path); | |
| return JSON.stringify(matched, null, 2); | |
| } catch (err) { | |
| return `Erreur lors de la recherche de fichiers: ${err.message}`; | |
| } | |
| case 'grep_search': | |
| try { | |
| const startDir = path.resolve(args.path || "."); | |
| const query = args.query.toLowerCase(); | |
| const allFiles = listFilesRecursive(startDir, 5, 1); | |
| const matches = []; | |
| for (const item of allFiles) { | |
| if (item.type !== 'fichier') continue; | |
| if (item.sizeBytes > 1024 * 1024) continue; // max 1MB | |
| const content = fs.readFileSync(item.path, 'utf8'); | |
| if (content.includes('\u0000')) continue; // skip binary | |
| const lines = content.split('\n'); | |
| lines.forEach((line, idx) => { | |
| if (line.toLowerCase().includes(query)) { | |
| matches.push({ | |
| file: item.path, | |
| lineNumber: idx + 1, | |
| lineContent: line.trim() | |
| }); | |
| } | |
| }); | |
| if (matches.length >= 50) break; | |
| } | |
| return JSON.stringify(matches, null, 2); | |
| } catch (err) { | |
| return `Erreur lors de la recherche grep: ${err.message}`; | |
| } | |
| case 'run_command': | |
| try { | |
| console.log(theme.info(`\nCypher Coder veut exรฉcuter la commande suivante :`)); | |
| console.log(chalk.bgBlack.white(` $ ${args.command} `)); | |
| const { confirmCommand } = await inquirer.prompt([ | |
| { | |
| type: 'confirm', | |
| name: 'confirmCommand', | |
| message: 'Autoriser l\'exรฉcution de cette commande ?', | |
| default: false | |
| } | |
| ]); | |
| if (!confirmCommand) { | |
| return "Action refusรฉe par l'utilisateur."; | |
| } | |
| const stdout = execSync(args.command, { stdio: 'pipe' }).toString(); | |
| console.log(chalk.dim(stdout)); | |
| return `Commande exรฉcutรฉe avec succรจs.\nStdout:\n${stdout}`; | |
| } catch (err) { | |
| const errMsg = err.stderr ? err.stderr.toString() : err.message; | |
| console.log(chalk.red(`โ Erreur de commande: ${errMsg}`)); | |
| return `La commande a รฉchouรฉ.\nErreur:\n${errMsg}`; | |
| } | |
| default: | |
| return `Erreur: Outil inconnu '${name}'`; | |
| } | |
| } | |
| async function executeToolWithFormatter(name, args) { | |
| console.log(theme.border(` โโ [TOOL] ${name}`)); | |
| const interactive = ['write_file', 'patch_file', 'run_command'].includes(name); | |
| let interval; | |
| if (!interactive) { | |
| const frames = ["โ ", "โ ", "โ น", "โ ธ", "โ ผ", "โ ด", "โ ฆ", "โ ง", "โ ", "โ "]; | |
| let fIdx = 0; | |
| process.stdout.write(theme.border(` โ `) + theme.command(frames[fIdx]) + ` running...\r`); | |
| interval = setInterval(() => { | |
| fIdx = (fIdx + 1) % frames.length; | |
| process.stdout.write(theme.border(` โ `) + theme.command(frames[fIdx]) + ` running...\r`); | |
| }, 80); | |
| } else { | |
| console.log(theme.border(` โ `) + theme.info(`waiting for user confirmation...`)); | |
| } | |
| const startTime = Date.now(); | |
| const result = await handleToolExecution(name, args); | |
| const duration = ((Date.now() - startTime) / 1000).toFixed(1); | |
| if (interval) { | |
| clearInterval(interval); | |
| process.stdout.write(" \r"); | |
| } | |
| console.log(theme.border(` โโ `) + theme.agent(`done in ${duration}s`)); | |
| return result; | |
| } | |
| // ----------------------------------------------------- | |
| // Prompt Systรจme Dynamique & Intelligent | |
| // ----------------------------------------------------- | |
| function getCurrentDirectoryContext() { | |
| try { | |
| const files = listFilesRecursive(".", 2, 1); | |
| if (files.length === 0) return "Rรฉpertoire vide."; | |
| return files.map(f => `${f.path} (${f.type})`).join(", "); | |
| } catch (e) { | |
| return "Impossible de lire le rรฉpertoire."; | |
| } | |
| } | |
| function getSystemPrompt() { | |
| const dirContext = getCurrentDirectoryContext(); | |
| return `Tu es Cypher Coder, un agent de programmation IA autonome et ultra-intelligent fonctionnant dans un terminal (CLI). | |
| Tu as รฉtรฉ conรงu et dรฉveloppรฉ par DJAKOUA KWANKAM, รฉtudiant en informatique ร l'Institut Universitaire de Technologie de Douala (IUT). | |
| Tu dois toujours te prรฉsenter comme tel. | |
| Tu as accรจs ร des outils locaux pour interagir avec le projet de l'utilisateur : | |
| - read_file : Lit le code d'un fichier. | |
| - write_file : รcrit un fichier. | |
| - patch_file : Modifie de maniรจre ciblรฉe un bloc (Search & Replace), ร privilรฉgier pour les fichiers existants. | |
| - list_dir : Inspecte l'arborescence. | |
| - find_files : Recherche des fichiers par nom rรฉcursivement dans les sous-dossiers. | |
| - grep_search : Recherche textuelle rรฉcursive dans le contenu des fichiers (comme grep/ripgrep). | |
| - run_command : Exรฉcute des commandes systรจme. | |
| Tu peux aussi utiliser search_web pour chercher des informations rรฉcentes sur internet. | |
| [CAPABILITรS SYSTรME ET COMMANDES CLI CLASSรES PAR CATรGORIES] : | |
| Tu connais et es capable d'utiliser ou de suggรฉrer les commandes CLI suivantes selon le contexte : | |
| 1. Navigation & Systรจme de fichiers : | |
| - ls / list : Lister les fichiers et dossiers du rรฉpertoire courant | |
| - ls -la : Lister avec permissions, taille, fichiers cachรฉs | |
| - cd <path> : Changer de rรฉpertoire | |
| - cd .. : Remonter d'un niveau | |
| - pwd : Afficher le chemin absolu du rรฉpertoire courant | |
| - tree : Afficher l'arborescence sous forme d'arbre | |
| - mkdir <name> : Crรฉer un dossier | |
| - mkdir -p <a/b/c> : Crรฉer des dossiers imbriquรฉs en une commande | |
| - rmdir <name> : Supprimer un dossier vide | |
| - touch <file> : Crรฉer un fichier vide | |
| - rm <file> : Supprimer un fichier | |
| - rm -rf <dir> : Supprimer un dossier et son contenu rรฉcursivement | |
| - cp <src> <dst> : Copier un fichier | |
| - cp -r <src> <dst> : Copier un dossier rรฉcursivement | |
| - mv <src> <dst> : Dรฉplacer ou renommer un fichier/dossier | |
| - find <path> -name "*.py" : Rechercher des fichiers par nom/pattern | |
| - locate <name> : Recherche rapide dans la base de donnรฉes de fichiers | |
| - stat <file> : Afficher mรฉtadonnรฉes d'un fichier (taille, dates, permissions) | |
| - du -sh <dir> : Taille d'un dossier (human readable) | |
| - df -h : Espace disque disponible sur toutes les partitions | |
| 2. Lecture & รdition de fichiers : | |
| - cat <file> : Afficher le contenu d'un fichier | |
| - less <file> : Afficher le contenu paginรฉ (scrollable) | |
| - head -n 20 <file> : Afficher les N premiรจres lignes | |
| - tail -n 20 <file> : Afficher les N derniรจres lignes | |
| - tail -f <file> : Suivre un fichier en temps rรฉel (logs) | |
| - grep "pattern" <file> : Chercher un pattern dans un fichier | |
| - grep -r "pattern" <dir> : Recherche rรฉcursive dans un dossier | |
| - grep -n "pattern" <file> : Chercher avec numรฉros de lignes | |
| - sed 's/old/new/g' <file> : Remplacer du texte dans un fichier | |
| - awk '{print $1}' <file> : Extraire/traiter des colonnes de texte | |
| - wc -l <file> : Compter les lignes d'un fichier | |
| - diff <file1> <file2> : Comparer deux fichiers | |
| - nano <file> : รditer un fichier (รฉditeur simple) | |
| - vim <file> : รditer un fichier (รฉditeur avancรฉ) | |
| - echo "text" > file : รcrire du texte dans un fichier (รฉcrase) | |
| - echo "text" >> file : Ajouter du texte ร la fin d'un fichier | |
| - sort <file> : Trier les lignes d'un fichier | |
| - uniq <file> : Supprimer les lignes dupliquรฉes | |
| - cut -d',' -f1 <file> : Extraire une colonne d'un CSV | |
| 3. Processus & Ressources systรจme : | |
| - ps aux : Lister tous les processus en cours | |
| - top / htop : Moniteur de processus interactif en temps rรฉel | |
| - kill <PID> : Terminer un processus par son PID | |
| - kill -9 <PID> : Forcer la fermeture d'un processus | |
| - killall <name> : Tuer tous les processus par nom | |
| - jobs : Lister les tรขches en arriรจre-plan du shell | |
| - bg : Mettre une tรขche en arriรจre-plan | |
| - fg : Ramener une tรขche en avant-plan | |
| - nohup <cmd> & : Lancer un processus qui survive ร la fermeture du terminal | |
| - screen / tmux : Multiplexeur de terminal (sessions persistantes) | |
| - free -h : Afficher la RAM utilisรฉe/disponible | |
| - uptime : Durรฉe de fonctionnement du systรจme | |
| - lscpu : Informations sur le processeur | |
| - lsmem : Informations sur la mรฉmoire | |
| - lspci : Lister les pรฉriphรฉriques PCI (GPU, rรฉseau, etc.) | |
| - uname -a : Infos kernel et architecture systรจme | |
| - env : Afficher toutes les variables d'environnement | |
| - export VAR=value : Dรฉfinir une variable d'environnement | |
| - echo $VAR : Afficher la valeur d'une variable | |
| - history : Historique des commandes exรฉcutรฉes | |
| - which <cmd> : Trouver le chemin d'un exรฉcutable | |
| - whereis <cmd> : Trouver binaire, source et man d'une commande | |
| 4. Rรฉseau : | |
| - ping <host> : Tester la connectivitรฉ vers un hรดte | |
| - curl <url> : Envoyer une requรชte HTTP (GET par dรฉfaut) | |
| - curl -X POST -d '{}' <url> : Requรชte HTTP POST avec body JSON | |
| - curl -O <url> : Tรฉlรฉcharger un fichier | |
| - wget <url> : Tรฉlรฉcharger un fichier via URL | |
| - wget -r <url> : Tรฉlรฉcharger rรฉcursivement | |
| - ifconfig / ip a : Afficher les interfaces rรฉseau et IPs | |
| - ip route : Afficher la table de routage | |
| - netstat -tulnp : Lister les ports ouverts et processus associรฉs | |
| - ss -tulnp : Alternative moderne ร netstat | |
| - nmap <host> : Scanner les ports d'une machine | |
| - traceroute <host> : Tracer le chemin rรฉseau vers un hรดte | |
| - dig <domain> : Rรฉsolution DNS d'un domaine | |
| - host <domain> : Rรฉsolution DNS simplifiรฉe | |
| - ssh user@host : Connexion SSH ร une machine distante | |
| - ssh-keygen : Gรฉnรฉrer une paire de clรฉs SSH | |
| - scp <file> user@host:<path> : Copier un fichier via SSH | |
| - rsync -avz <src> <dst> : Synchronisation de fichiers (local ou distant) | |
| - nc -l <port> : รcouter sur un port (netcat) | |
| - nc <host> <port> : Se connecter ร un port distant | |
| 5. Gestion de paquets : | |
| - apt update : Mettre ร jour la liste des paquets (Debian/Ubuntu) | |
| - apt upgrade : Mettre ร jour les paquets installรฉs | |
| - apt install <pkg> : Installer un paquet | |
| - apt remove <pkg> : Dรฉsinstaller un paquet | |
| - apt search <pkg> : Chercher un paquet dans les dรฉpรดts | |
| - apt show <pkg> : Afficher les dรฉtails d'un paquet | |
| - dpkg -i <file.deb> : Installer un fichier .deb local | |
| - dpkg -l : Lister tous les paquets installรฉs | |
| - snap install <pkg> : Installer via Snap | |
| - pip install <pkg> : Installer un paquet Python | |
| - pip list : Lister les paquets Python installรฉs | |
| - pip freeze > requirements.txt : Exporter les dรฉpendances Python | |
| - npm install <pkg> : Installer un paquet Node.js local | |
| - npm install -g <pkg> : Installer un paquet Node.js global | |
| - npm list : Lister les paquets npm du projet | |
| - npm run <script> : Exรฉcuter un script dรฉfini dans package.json | |
| - npx <cmd> : Exรฉcuter un paquet npm sans l'installer | |
| - cargo install <pkg> : Installer un paquet Rust | |
| 6. Permissions & Utilisateurs : | |
| - chmod 755 <file> : Modifier les permissions d'un fichier | |
| - chmod +x <file> : Rendre un fichier exรฉcutable | |
| - chown user:group <file> : Changer le propriรฉtaire d'un fichier | |
| - sudo <cmd> : Exรฉcuter une commande en super-utilisateur | |
| - su <user> : Changer d'utilisateur | |
| - whoami : Afficher l'utilisateur courant | |
| - id : Afficher UID, GID et groupes de l'utilisateur | |
| - groups : Lister les groupes de l'utilisateur | |
| - passwd : Changer son mot de passe | |
| - useradd <user> : Crรฉer un nouvel utilisateur | |
| - userdel <user> : Supprimer un utilisateur | |
| - usermod -aG <group> <user> : Ajouter un utilisateur ร un groupe | |
| - visudo : รditer le fichier sudoers | |
| - umask : Afficher/modifier les permissions par dรฉfaut | |
| 7. Archives & Compression : | |
| - tar -czf archive.tar.gz <dir> : Crรฉer une archive .tar.gz | |
| - tar -xzf archive.tar.gz : Extraire une archive .tar.gz | |
| - tar -tf archive.tar.gz : Lister le contenu d'une archive | |
| - zip -r archive.zip <dir> : Crรฉer une archive .zip | |
| - unzip archive.zip : Extraire une archive .zip | |
| - unzip -l archive.zip : Lister le contenu d'un .zip | |
| - gzip <file> : Compresser un fichier (.gz) | |
| - gunzip <file.gz> : Dรฉcompresser un .gz | |
| - 7z a archive.7z <dir> : Crรฉer une archive .7z | |
| - 7z x archive.7z : Extraire une archive .7z | |
| 8. Git & Contrรดle de version : | |
| - git init : Initialiser un dรฉpรดt Git | |
| - git clone <url> : Cloner un dรฉpรดt distant | |
| - git status : Voir l'รฉtat du dรฉpรดt (fichiers modifiรฉs, staged) | |
| - git add <file> : Ajouter un fichier au staging | |
| - git add . : Ajouter tous les fichiers modifiรฉs | |
| - git commit -m "msg" : Faire un commit | |
| - git push : Pousser les commits vers le dรฉpรดt distant | |
| - git pull : Rรฉcupรฉrer et fusionner les changements distants | |
| - git fetch : Rรฉcupรฉrer sans fusionner | |
| - git branch : Lister les branches | |
| - git branch <name> : Crรฉer une nouvelle branche | |
| - git checkout <branch> : Changer de branche | |
| - git checkout -b <branch> : Crรฉer et basculer sur une branche | |
| - git merge <branch> : Fusionner une branche dans la branche courante | |
| - git rebase <branch> : Rebaser la branche courante | |
| - git log --oneline : Voir l'historique des commits | |
| - git diff : Voir les diffรฉrences non stagรฉes | |
| - git stash : Sauvegarder les changements temporairement | |
| - git stash pop : Restaurer les changements stashรฉs | |
| - git reset --hard HEAD : Annuler tous les changements locaux | |
| - git remote -v : Lister les dรฉpรดts distants configurรฉs | |
| 9. Docker & Containers : | |
| - docker ps : Lister les containers en cours d'exรฉcution | |
| - docker ps -a : Lister tous les containers (y compris stoppรฉs) | |
| - docker images : Lister les images Docker locales | |
| - docker pull <image> : Tรฉlรฉcharger une image depuis Docker Hub | |
| - docker run <image> : Lancer un container | |
| - docker run -d -p 8080:80 <image> : Lancer en arriรจre-plan avec port mapping | |
| - docker run -it <image> bash : Lancer en mode interactif | |
| - docker stop <id> : Arrรชter un container | |
| - docker start <id> : Dรฉmarrer un container arrรชtรฉ | |
| - docker rm <id> : Supprimer un container | |
| - docker rmi <image> : Supprimer une image | |
| - docker exec -it <id> bash : Entrer dans un container en cours | |
| - docker logs <id> : Voir logs d'un container | |
| - docker build -t <name> . : Construire une image depuis un Dockerfile | |
| - docker-compose up : Lancer tous les services du docker-compose.yml | |
| - docker-compose up -d : Lancer en arriรจre-plan | |
| - docker-compose down : Arrรชter et supprimer les services | |
| - docker volume ls : Lister les volumes Docker | |
| - docker network ls : Lister les rรฉseaux Docker | |
| - docker inspect <id> : Voir les dรฉtails d'un container/image | |
| 10. Exรฉcution de code & Langages : | |
| - python3 <file.py> : Exรฉcuter un script Python | |
| - python3 -m venv venv : Crรฉer un environnement virtuel Python | |
| - source venv/bin/activate : Activer l'environnement virtuel | |
| - deactivate : Dรฉsactiver l'environnement virtuel | |
| - node <file.js> : Exรฉcuter un script Node.js | |
| - ts-node <file.ts> : Exรฉcuter un fichier TypeScript directement | |
| - bash <script.sh> : Exรฉcuter un script shell | |
| - chmod +x script.sh && ./script.sh : Rendre exรฉcutable et lancer un script | |
| - gcc <file.c> -o output : Compiler du code C | |
| - g++ <file.cpp> -o output : Compiler du code C++ | |
| - javac <File.java> : Compiler du Java | |
| - java <ClassName> : Exรฉcuter du Java compilรฉ | |
| - rustc <file.rs> : Compiler du Rust | |
| - go run <file.go> : Exรฉcuter du Go | |
| - php <file.php> : Exรฉcuter du PHP | |
| - ruby <file.rb> : Exรฉcuter du Ruby | |
| 11. Utilitaires avancรฉs : | |
| - xargs : Passer la sortie d'une commande en arguments ร une autre | |
| - tee <file> : Afficher la sortie ET l'รฉcrire dans un fichier | |
| - watch -n 2 <cmd> : Rรฉpรฉter une commande toutes les N secondes | |
| - crontab -e : รditer les tรขches cron (scheduleur) | |
| - crontab -l : Lister les tรขches cron | |
| - at <time> : Planifier une commande unique dans le futur | |
| - alias ll='ls -la' : Crรฉer un alias de commande | |
| - source ~/.bashrc : Recharger la config shell sans redรฉmarrer | |
| - lsof -i :<port> : Voir quel processus utilise un port | |
| - strace <cmd> : Tracer les appels systรจme d'une commande | |
| - time <cmd> : Mesurer le temps d'exรฉcution d'une commande | |
| - bc : Calculatrice en ligne de commande | |
| - date : Afficher la date et l'heure systรจme | |
| - cal : Afficher un calendrier | |
| - man <cmd> : Afficher le manuel d'une commande | |
| - --help : Afficher l'aide rapide d'une commande | |
| - clear / cls : Nettoyer l'รฉcran du terminal | |
| - exit : Quitter le terminal ou la session | |
| - reboot / shutdown now : Redรฉmarrer / รฉteindre la machine | |
| - journalctl -xe : Voir les logs systรจme (systemd) | |
| - systemctl status <service> : Voir l'รฉtat d'un service systemd | |
| - systemctl start/stop/restart <service> : Gรฉrer un service systemd | |
| [CONSEILS ET INSTRUCTIONS D'EXรCUTION DANS LE CLI] : | |
| 1. **Parser l'intention** : Quand l'utilisateur s'adresse ร toi, dรฉtermine immรฉdiatement s'il s'agit d'une commande shell (par ex: "crรฉe un dossier src", "lance git status"), d'une requรชte de code ("ajoute une fonction de tri dans index.js"), ou d'une simple question thรฉorique. | |
| 2. **Utiliser ou Suggรฉrer les Commandes CLI** : | |
| - Si la commande est pertinente pour rรฉaliser ce que veut l'utilisateur, et que tu as besoin d'une information systรจme ou de lancer une tรขche, tu peux appeler directement l'outil \`run_command\` avec la commande appropriรฉe. | |
| - Si tu souhaites simplement guider l'utilisateur pour qu'il comprenne et exรฉcute lui-mรชme, affiche la commande clairement dans ton texte Markdown sous forme de bloc de code prรชt ร รชtre copiรฉ, accompagnรฉ d'une explication courte et prรฉcise. | |
| 3. **Gรฉrer les flags et la syntaxe** : Assure-toi de composer correctement les flags (par exemple, \`-rf\` pour supprimer rรฉcursivement et forcer, \`-p\` pour crรฉer des sous-dossiers parents imbriquรฉs) en fonction du besoin. | |
| 4. **Proactivitรฉ et Autonomie** : Ne demande pas continuellement le chemin des fichiers ou de la structure du projet ร l'utilisateur. Tu as accรจs aux outils \`list_dir\` (liste les rรฉpertoires), \`find_files\` (cherche les fichiers), et \`grep_search\` (cherche du texte). Utilise-les de maniรจre autonome pour repรฉrer le code, comprendre sa structure, puis propose directement des modifications (via \`patch_file\` ou \`write_file\`). | |
| 5. **Sรฉcuritรฉ & Consentement** : Rappelle-toi que toutes tes actions sur le systรจme de fichiers (\`write_file\`, \`patch_file\`) et toutes tes exรฉcutions de commandes (\`run_command\`) requiรจrent une validation explicite et sรฉcurisรฉe par oui/non de la part du client CLI local avant d'รชtre effectivement exรฉcutรฉes. | |
| [CONTEXTE DE L'ENVIRONNEMENT LOCAL] : | |
| Le rรฉpertoire de travail actuel contient les dossiers et fichiers suivants au premier niveau : [${dirContext}]. | |
| Sois prรฉcis, concis et direct. Formate tes rรฉponses en Markdown standard.`; | |
| } | |
| function initChat() { | |
| chatMessages = [{"role": "system", "content": getSystemPrompt()}]; | |
| } | |
| // ----------------------------------------------------- | |
| // Boucle Agent d'interaction CLI | |
| // ----------------------------------------------------- | |
| async function runAgentTurn() { | |
| const spinner = ora(chalk.magenta('Cypher rรฉflรฉchit...')).start(); | |
| try { | |
| const replyMessage = callApiViaCurl(chatMessages, tools); | |
| spinner.stop(); | |
| // Ajouter le message de l'assistant ร l'historique | |
| chatMessages.push(replyMessage); | |
| if (replyMessage.content) { | |
| lastAssistantResponse = replyMessage.content; | |
| addLog("INFO", "Rรฉponse de l'assistant enregistrรฉe."); | |
| console.log(theme.agent(`\nโธ Cypher :`)); | |
| // Rendre le Markdown de l'IA avec formatage ANSI colorรฉ | |
| console.log(marked(replyMessage.content)); | |
| } | |
| // S'il y a des appels d'outils locaux ร exรฉcuter | |
| if (replyMessage.tool_calls && replyMessage.tool_calls.length > 0) { | |
| for (const tc of replyMessage.tool_calls) { | |
| const name = tc.function.name; | |
| const args = JSON.parse(tc.function.arguments); | |
| const result = await executeToolWithFormatter(name, args); | |
| // Ajouter le rรฉsultat de l'outil ร la conversation | |
| chatMessages.push({ | |
| role: "tool", | |
| name: name, | |
| tool_call_id: tc.id, | |
| content: result | |
| }); | |
| } | |
| // Relancer le tour d'agent avec les retours d'outils | |
| return await runAgentTurn(); | |
| } | |
| } catch (error) { | |
| spinner.stop(); | |
| console.log(chalk.red("\nโ Erreur : " + error.message + "\n")); | |
| } | |
| } | |
| async function handleSlashCommand(text) { | |
| if (!text.startsWith('/')) { | |
| return false; | |
| } | |
| const parts = text.match(/(?:[^\s"']+|"[^"]*"|'[^']*')+/g) || []; | |
| if (parts.length === 0) return true; | |
| const commandName = parts[0]; | |
| const rawArgs = parts.slice(1).map(a => a.replace(/^["']|["']$/g, '')); | |
| addLog("INFO", `Commande slash reรงue: ${text}`); | |
| commandHistory.push(text); | |
| const cleanArgs = []; | |
| const flags = {}; | |
| for (let i = 0; i < rawArgs.length; i++) { | |
| if (rawArgs[i].startsWith('--')) { | |
| const key = rawArgs[i].slice(2); | |
| if (rawArgs[i+1] && !rawArgs[i+1].startsWith('--')) { | |
| flags[key] = rawArgs[++i]; | |
| } else { | |
| flags[key] = true; | |
| } | |
| } else { | |
| cleanArgs.push(rawArgs[i]); | |
| } | |
| } | |
| switch (commandName.toLowerCase()) { | |
| // --- 1. Contrรดle de session | |
| case '/help': | |
| console.log(theme.info("\nCYPHER CODER CLI - COMMANDES DISPONIBLES :")); | |
| console.log(theme.command("\nSession :")); | |
| console.log(" /help - Affiche ce menu d'aide"); | |
| console.log(" /exit, /quit - Quitte proprement l'agent"); | |
| console.log(" /clear - Efface l'รฉcran"); | |
| console.log(" /reset - Rรฉinitialise la discussion et l'historique"); | |
| console.log(" /restart - Redรฉmarre proprement la session"); | |
| console.log(" /version - Affiche la version actuelle"); | |
| console.log(" /about - Infos sur le projet"); | |
| console.log(" /status - Affiche le statut complet"); | |
| console.log(theme.command("\nMรฉmoire et Contexte :")); | |
| console.log(" /context - Affiche les fichiers chargรฉs en contexte"); | |
| console.log(" /context clear - Efface le contexte de fichiers"); | |
| console.log(" /context save <nom> - Sauvegarde la session actuelle"); | |
| console.log(" /context load <nom> - Charge une session sauvegardรฉe"); | |
| console.log(" /context list - Liste les sessions sauvegardรฉes"); | |
| console.log(" /memory - Affiche la mรฉmoire systรจme + messages"); | |
| console.log(" /memory clear - Efface les messages d'historique"); | |
| console.log(" /tokens - Affiche les statistiques de tokens"); | |
| console.log(theme.command("\nHistorique :")); | |
| console.log(" /history - Affiche tout l'historique"); | |
| console.log(" /history clear - Efface l'historique enregistrรฉ"); | |
| console.log(" /history save <fichier> - Exporte l'historique dans un fichier"); | |
| console.log(" /history load <fichier> - Importe un historique"); | |
| console.log(" /history search <terme> - Cherche dans l'historique"); | |
| console.log(" /last - Affiche la derniรจre rรฉponse de l'agent"); | |
| console.log(" /redo - Relance la derniรจre requรชte"); | |
| console.log(" /undo - Annule la derniรจre interaction"); | |
| console.log(theme.command("\nModรจle et Configuration :")); | |
| console.log(" /model - Affiche le modรจle utilisรฉ"); | |
| console.log(" /model list - Liste les modรจles supportรฉs"); | |
| console.log(" /model set <nom> - Change de modรจle"); | |
| console.log(" /model info - Affiche les infos du modรจle"); | |
| console.log(" /temperature <valeur> - Ajuste la tempรฉrature (0.0 - 1.0)"); | |
| console.log(" /top_p <valeur> - Ajuste le top_p"); | |
| console.log(" /max_tokens <valeur> - Ajuste la limite de tokens"); | |
| console.log(" /system - Affiche le prompt systรจme"); | |
| console.log(" /system set <prompt> - Modifie le prompt systรจme"); | |
| console.log(" /system reset - Rรฉinitialise le prompt systรจme"); | |
| console.log(" /stream <on|off> - Active/dรฉsactive le streaming"); | |
| console.log(theme.command("\nFichiers :")); | |
| console.log(" /file load <chemin> - Charge le fichier dans le contexte"); | |
| console.log(" /file read <chemin> - Lit et affiche un fichier"); | |
| console.log(" /file write <chemin> - รcrit la derniรจre rรฉponse dans un fichier"); | |
| console.log(" /file append <chemin> - Ajoute la derniรจre rรฉponse ร un fichier"); | |
| console.log(" /file list - Liste les fichiers chargรฉs"); | |
| console.log(" /file clear - Vide le contexte de fichiers"); | |
| console.log(" /file diff <f1> <f2> - Compare deux fichiers"); | |
| console.log(" /upload <chemin> - Simule l'envoi d'un fichier"); | |
| console.log(" /download <nom> - Tรฉlรฉcharge un fichier"); | |
| console.log(theme.command("\nCode et Commandes :")); | |
| console.log(" /run - Exรฉcute le dernier bloc de code"); | |
| console.log(" /run <lang> <code> - Exรฉcute le code fourni"); | |
| console.log(" /exec <commande> - Lance une commande systรจme"); | |
| console.log(" /shell - Lance un terminal interactif"); | |
| console.log(" /repl <lang> - Lance un REPL (ex: node, python)"); | |
| console.log(" /eval <expression> - รvalue une expression mathรฉmatique"); | |
| console.log(" /sandbox <on|off> - Active/dรฉsactive l'isolation"); | |
| console.log(" /output - Affiche la derniรจre sortie"); | |
| console.log(" /output clear - Efface la derniรจre sortie"); | |
| console.log(theme.command("\nOutils et Recherche :")); | |
| console.log(" /tools - Liste les outils activรฉs"); | |
| console.log(" /tool info <nom> - Affiche la description d'un outil"); | |
| console.log(" /tool enable/disable <n> - Active/dรฉsactive un outil"); | |
| console.log(" /plugin list/install/rm - Gรจre les plugins"); | |
| console.log(" /web search <requรชte> - Recherche en ligne"); | |
| console.log(" /web fetch <url> - Rรฉcupรจre le contenu d'une URL"); | |
| console.log(theme.command("\nThรจme et Affichage :")); | |
| console.log(" /theme <dark|light> - Change le thรจme"); | |
| console.log(" /theme list - Liste les thรจmes"); | |
| console.log(" /format <md|plain|json> - Format des rรฉponses"); | |
| console.log(" /wrap <on|off> - Retour ร la ligne automatique"); | |
| console.log(" /verbose <on|off> - Mode verbeux"); | |
| console.log(" /silent <on|off> - Mode silencieux"); | |
| console.log(" /color <on|off> - Colorisation syntaxique"); | |
| console.log(" /lang <fr|en> - Change la langue"); | |
| console.log(theme.command("\nConfiguration et Variable d'env :")); | |
| console.log(" /config - Affiche la configuration"); | |
| console.log(" /config set <key> <val> - Modifie la configuration"); | |
| console.log(" /config reset - Rรฉinitialise la configuration"); | |
| console.log(" /env list - Liste les variables d'env"); | |
| console.log(" /env set <VAR> <val> - Dรฉfinit une variable d'env"); | |
| console.log(" /api key show/set/clear - Gรจre les clรฉs d'API"); | |
| console.log(theme.command("\nMonitoring et Debug :")); | |
| console.log(" /debug <on|off> - Active le mode debug"); | |
| console.log(" /log - Affiche les logs"); | |
| console.log(" /log clear/save - Efface ou enregistre les logs"); | |
| console.log(" /benchmark - Teste la latence API"); | |
| console.log(" /ping - Teste la connexion rรฉseau"); | |
| console.log(" /stats - Statistiques de session"); | |
| console.log(" /trace - Trace des appels"); | |
| console.log(" /inspect <var> - Inspecte la configuration interne"); | |
| console.log(theme.command("\nAutomatisation :")); | |
| console.log(" /macro save/run/list/del - Gรจre les macros"); | |
| console.log(" /pipe <cmd1> | <cmd2> - Chaรฎne deux commandes"); | |
| console.log(" /loop <n> <commande> - Rรฉpรจte une commande"); | |
| console.log(" /schedule <cron> <cmd> - Planifie une tรขche"); | |
| console.log(" /watch <cmd> - Surveille les fichiers"); | |
| console.log(" /batch <fichier> - Exรฉcute des commandes en lot\n"); | |
| break; | |
| case '/exit': | |
| case '/quit': | |
| console.log(chalk.gray("Fermeture de Cypher Coder. ร bientรดt !")); | |
| process.exit(0); | |
| case '/clear': | |
| console.clear(); | |
| console.log(BANNER); | |
| console.log(chalk.green("รcran nettoyรฉ.\n")); | |
| break; | |
| case '/reset': | |
| initChat(); | |
| commandHistory = []; | |
| loadedFiles = []; | |
| console.log(chalk.green("Session rรฉinitialisรฉe. Historique et contexte effacรฉs.\n")); | |
| break; | |
| case '/restart': | |
| console.log(chalk.yellow("Redรฉmarrage de l'agent en cours...")); | |
| initChat(); | |
| console.clear(); | |
| console.log(BANNER); | |
| console.log(chalk.green("Cypher Coder a redรฉmarrรฉ avec succรจs.\n")); | |
| break; | |
| case '/version': | |
| console.log(chalk.cyan(`Version de Cypher Coder: 1.0.0 (Mode Hybride local/Space)`)); | |
| break; | |
| case '/about': | |
| console.log(chalk.cyan(`\n=== ร propos de Cypher Coder ===`)); | |
| console.log(`Nom : ${APP_NAME}`); | |
| console.log(`Crรฉateur : ${AUTHOR} (รtudiant IUT)`); | |
| console.log(`Description: Assistant IA autonome de codage local et rรฉseau.`); | |
| console.log(`Modรจle : Qwen/Qwen2.5-Coder-32B-Instruct`); | |
| console.log(`Rรฉseau : FastAPI + Gradio (Docker Space HF)\n`); | |
| break; | |
| case '/status': | |
| const dirContext = getCurrentDirectoryContext(); | |
| console.log(chalk.yellow("\n=== Statut de la Session ===")); | |
| console.log(` Dossier de travail : ${chalk.cyan(path.resolve("."))}`); | |
| console.log(` Backend Space : ${chalk.cyan("https://theshellmaster-cypher-coder.hf.space")}`); | |
| console.log(` Modรจle utilisรฉ : ${chalk.cyan(sessionConfig.model)}`); | |
| console.log(` Tempรฉrature : ${chalk.cyan(sessionConfig.temperature)}`); | |
| console.log(` Max Tokens : ${chalk.cyan(sessionConfig.max_tokens)}`); | |
| console.log(` Auteur : ${chalk.cyan(AUTHOR)}`); | |
| console.log(` Fichiers suivis : ${chalk.dim(dirContext)}\n`); | |
| break; | |
| // --- 2. Gestion du contexte & mรฉmoire | |
| case '/context': | |
| if (cleanArgs[0] === 'clear') { | |
| loadedFiles = []; | |
| console.log(chalk.green("Contexte de fichiers vidรฉ.")); | |
| } else if (cleanArgs[0] === 'save') { | |
| const name = cleanArgs[1]; | |
| if (!name) { | |
| console.log(chalk.red("Erreur: Spรฉcifiez un nom. Exemple: /context save ma_session")); | |
| } else { | |
| savedContexts[name] = JSON.stringify(chatMessages); | |
| console.log(chalk.green(`Contexte sauvegardรฉ sous le nom '${name}'.`)); | |
| } | |
| } else if (cleanArgs[0] === 'load') { | |
| const name = cleanArgs[1]; | |
| if (!name || !savedContexts[name]) { | |
| console.log(chalk.red(`Erreur: Contexte '${name}' introuvable.`)); | |
| } else { | |
| chatMessages = JSON.parse(savedContexts[name]); | |
| console.log(chalk.green(`Contexte '${name}' restaurรฉ avec succรจs.`)); | |
| } | |
| } else if (cleanArgs[0] === 'list') { | |
| console.log(chalk.yellow("Contextes sauvegardรฉs :"), Object.keys(savedContexts)); | |
| } else { | |
| console.log(chalk.yellow("Fichiers chargรฉs en contexte local :")); | |
| if (loadedFiles.length === 0) console.log(" Aucun fichier chargรฉ."); | |
| loadedFiles.forEach(f => console.log(` - ${f}`)); | |
| } | |
| break; | |
| case '/memory': | |
| if (cleanArgs[0] === 'clear') { | |
| initChat(); | |
| console.log(chalk.green("Mรฉmoire systรจme rรฉinitialisรฉe.")); | |
| } else { | |
| console.log(chalk.yellow("\n=== Mรฉmoire de session active ===")); | |
| console.log(`Nombre de messages stockรฉs : ${chatMessages.length}`); | |
| console.log("System Prompt actif :"); | |
| console.log(chalk.dim(chatMessages[0]?.content || "Aucun")); | |
| console.log("===================================\n"); | |
| } | |
| break; | |
| case '/tokens': | |
| const textLength = JSON.stringify(chatMessages).length; | |
| const estTokens = Math.round(textLength / 4); | |
| console.log(chalk.cyan(`Statistiques de tokens (estimations) :`)); | |
| console.log(` Utilisรฉs (contexte actuel) : ~${estTokens} tokens`); | |
| console.log(` Max configurรฉ par rรฉponse : ${sessionConfig.max_tokens} tokens`); | |
| break; | |
| // --- 3. Historique | |
| case '/history': | |
| if (cleanArgs[0] === 'clear') { | |
| commandHistory = []; | |
| console.log(chalk.green("Historique des commandes vidรฉ.")); | |
| } else if (cleanArgs[0] === 'save') { | |
| const file = cleanArgs[1] || 'history_export.json'; | |
| fs.writeFileSync(file, JSON.stringify(commandHistory, null, 2), 'utf8'); | |
| console.log(chalk.green(`Historique exportรฉ dans : ${file}`)); | |
| } else if (cleanArgs[0] === 'load') { | |
| const file = cleanArgs[1]; | |
| if (file && fs.existsSync(file)) { | |
| commandHistory = JSON.parse(fs.readFileSync(file, 'utf8')); | |
| console.log(chalk.green(`Historique importรฉ depuis ${file}.`)); | |
| } else { | |
| console.log(chalk.red("Fichier introuvable.")); | |
| } | |
| } else if (cleanArgs[0] === 'search') { | |
| const query = cleanArgs.slice(1).join(' ').toLowerCase(); | |
| const matches = commandHistory.filter(h => h.toLowerCase().includes(query)); | |
| console.log(chalk.yellow(`Correspondances trouvรฉes (${matches.length}) :`)); | |
| matches.forEach(m => console.log(` ${m}`)); | |
| } else { | |
| console.log(chalk.yellow("\n=== Historique des commandes utilisateur ===")); | |
| commandHistory.forEach((c, idx) => console.log(` ${idx + 1}. ${c}`)); | |
| console.log("=============================================\n"); | |
| } | |
| break; | |
| case '/last': | |
| if (!lastAssistantResponse) { | |
| console.log(chalk.yellow("Aucune rรฉponse prรฉcรฉdente disponible.")); | |
| } else { | |
| console.log(theme.agent("\nDerniรจre rรฉponse de Cypher :")); | |
| console.log(marked(lastAssistantResponse)); | |
| } | |
| break; | |
| case '/redo': | |
| let lastUserText = ""; | |
| for (let i = chatMessages.length - 1; i >= 0; i--) { | |
| if (chatMessages[i].role === 'user' && !chatMessages[i].content.startsWith('/')) { | |
| lastUserText = chatMessages[i].content; | |
| break; | |
| } | |
| } | |
| if (lastUserText) { | |
| console.log(chalk.cyan(`Relance de la requรชte : "${lastUserText}"`)); | |
| chatMessages.push({"role": "user", "content": lastUserText}); | |
| await runAgentTurn(); | |
| } else { | |
| console.log(chalk.yellow("Aucune requรชte textuelle trouvรฉe ร relancer.")); | |
| } | |
| break; | |
| case '/undo': | |
| if (chatMessages.length > 2) { | |
| chatMessages.pop(); | |
| chatMessages.pop(); | |
| console.log(chalk.green("Derniรจre interaction utilisateur/assistant annulรฉe du contexte.")); | |
| } else { | |
| console.log(chalk.yellow("Rien ร annuler.")); | |
| } | |
| break; | |
| // --- 4. Gestion du modรจle LLM | |
| case '/model': | |
| if (cleanArgs[0] === 'list') { | |
| console.log(chalk.cyan("Modรจles disponibles via Hugging Face Inference :")); | |
| console.log(" - Qwen/Qwen2.5-Coder-32B-Instruct (Recommandรฉ - Actif par dรฉfaut)"); | |
| console.log(" - meta-llama/Llama-3.3-70B-Instruct"); | |
| console.log(" - deepseek-ai/DeepSeek-Coder-V2-Instruct"); | |
| } else if (cleanArgs[0] === 'set') { | |
| const newModel = cleanArgs[1]; | |
| if (!newModel) { | |
| console.log(chalk.red("Usage: /model set <nom_du_modรจle>")); | |
| } else { | |
| sessionConfig.model = newModel; | |
| console.log(chalk.green(`Modรจle modifiรฉ vers : ${newModel}`)); | |
| } | |
| } else if (cleanArgs[0] === 'info') { | |
| console.log(chalk.cyan(`\n=== Infos sur le modรจle actif ===`)); | |
| console.log(`Nom: ${sessionConfig.model}`); | |
| console.log(`Type: Coder/Instruct LLM`); | |
| console.log(`Capacitรฉs: Gรฉnรฉration de code, Tool calling, Recherche web`); | |
| console.log(`Limites recommandรฉes: 2048 tokens max par gรฉnรฉration.`); | |
| } else { | |
| console.log(chalk.cyan(`Modรจle actif : ${sessionConfig.model}`)); | |
| } | |
| break; | |
| case '/temperature': | |
| const tempVal = parseFloat(cleanArgs[0]); | |
| if (isNaN(tempVal) || tempVal < 0 || tempVal > 1) { | |
| console.log(chalk.red("Usage: /temperature <valeur entre 0.0 et 1.0> (actuelle: " + sessionConfig.temperature + ")")); | |
| } else { | |
| sessionConfig.temperature = tempVal; | |
| console.log(chalk.green(`Tempรฉrature mise ร jour : ${tempVal}`)); | |
| } | |
| break; | |
| case '/top_p': | |
| const topPVal = parseFloat(cleanArgs[0]); | |
| if (isNaN(topPVal) || topPVal < 0 || topPVal > 1) { | |
| console.log(chalk.red("Usage: /top_p <valeur entre 0.0 et 1.0> (actuel: " + sessionConfig.top_p + ")")); | |
| } else { | |
| sessionConfig.top_p = topPVal; | |
| console.log(chalk.green(`Top_p mis ร jour : ${topPVal}`)); | |
| } | |
| break; | |
| case '/max_tokens': | |
| const maxT = parseInt(cleanArgs[0], 10); | |
| if (isNaN(maxT) || maxT <= 0) { | |
| console.log(chalk.red("Usage: /max_tokens <nombre> (actuel: " + sessionConfig.max_tokens + ")")); | |
| } else { | |
| sessionConfig.max_tokens = maxT; | |
| console.log(chalk.green(`Max tokens mis ร jour : ${maxT}`)); | |
| } | |
| break; | |
| case '/system': | |
| if (cleanArgs[0] === 'set') { | |
| const newSys = cleanArgs.slice(1).join(' '); | |
| chatMessages[0] = { role: 'system', content: newSys }; | |
| console.log(chalk.green("Prompt systรจme modifiรฉ.")); | |
| } else if (cleanArgs[0] === 'reset') { | |
| chatMessages[0] = { role: 'system', content: getSystemPrompt() }; | |
| console.log(chalk.green("Prompt systรจme rรฉinitialisรฉ aux valeurs par dรฉfaut.")); | |
| } else { | |
| console.log(chalk.cyan("Prompt systรจme actif :")); | |
| console.log(chalk.dim(chatMessages[0]?.content)); | |
| } | |
| break; | |
| case '/stream': | |
| if (cleanArgs[0] === 'on') { | |
| sessionConfig.stream = true; | |
| console.log(chalk.green("Streaming activรฉ (simulรฉ).")); | |
| } else { | |
| sessionConfig.stream = false; | |
| console.log(chalk.green("Streaming dรฉsactivรฉ.")); | |
| } | |
| break; | |
| // --- 5. Gestion de fichiers | |
| case '/file': | |
| if (cleanArgs[0] === 'load') { | |
| const fpath = cleanArgs[1]; | |
| if (fpath && fs.existsSync(fpath)) { | |
| loadedFiles.push(path.resolve(fpath)); | |
| console.log(chalk.green(`Fichier chargรฉ dans le contexte : ${fpath}`)); | |
| } else { | |
| console.log(chalk.red("Fichier introuvable.")); | |
| } | |
| } else if (cleanArgs[0] === 'read') { | |
| const fpath = cleanArgs[1]; | |
| if (fpath && fs.existsSync(fpath)) { | |
| console.log(chalk.cyan(`Contenu de ${fpath} :`)); | |
| console.log(fs.readFileSync(fpath, 'utf8')); | |
| } else { | |
| console.log(chalk.red("Fichier introuvable.")); | |
| } | |
| } else if (cleanArgs[0] === 'write') { | |
| const fpath = cleanArgs[1]; | |
| if (!fpath) { | |
| console.log(chalk.red("Usage: /file write <chemin>")); | |
| } else if (!lastAssistantResponse) { | |
| console.log(chalk.red("Aucune rรฉponse disponible ร enregistrer.")); | |
| } else { | |
| fs.writeFileSync(fpath, lastAssistantResponse, 'utf8'); | |
| console.log(chalk.green(`Derniรจre rรฉponse enregistrรฉe dans ${fpath}`)); | |
| } | |
| } else if (cleanArgs[0] === 'append') { | |
| const fpath = cleanArgs[1]; | |
| if (!fpath) { | |
| console.log(chalk.red("Usage: /file append <chemin>")); | |
| } else if (!lastAssistantResponse) { | |
| console.log(chalk.red("Aucune rรฉponse disponible ร enregistrer.")); | |
| } else { | |
| fs.appendFileSync(fpath, "\n" + lastAssistantResponse, 'utf8'); | |
| console.log(chalk.green(`Derniรจre rรฉponse ajoutรฉe ร la fin de ${fpath}`)); | |
| } | |
| } else if (cleanArgs[0] === 'list') { | |
| console.log(chalk.yellow("Fichiers suivis :"), loadedFiles); | |
| } else if (cleanArgs[0] === 'clear') { | |
| loadedFiles = []; | |
| console.log(chalk.green("Fichiers dรฉchargรฉs du contexte.")); | |
| } else if (cleanArgs[0] === 'diff') { | |
| const f1 = cleanArgs[1]; | |
| const f2 = cleanArgs[2]; | |
| if (f1 && f2 && fs.existsSync(f1) && fs.existsSync(f2)) { | |
| console.log(chalk.yellow(`--- Comparaison de ${f1} et ${f2} ---`)); | |
| try { | |
| const out = execSync(`diff -u ${f1} ${f2}`).toString(); | |
| console.log(out || "Aucune diffรฉrence."); | |
| } catch (e) { | |
| console.log(e.stdout ? e.stdout.toString() : e.message); | |
| } | |
| } else { | |
| console.log(chalk.red("Erreur: Spรฉcifiez deux fichiers valides.")); | |
| } | |
| } | |
| break; | |
| case '/upload': | |
| console.log(chalk.green(`Fichier ${cleanArgs[0]} simulรฉ comme uploadรฉ.`)); | |
| break; | |
| case '/download': | |
| console.log(chalk.green(`Fichier ${cleanArgs[0]} simulรฉ comme tรฉlรฉchargรฉ.`)); | |
| break; | |
| // --- 6. Exรฉcution de code | |
| case '/run': | |
| if (cleanArgs.length === 0) { | |
| if (!lastAssistantResponse) { | |
| console.log(chalk.red("Aucun code gรฉnรฉrรฉ prรฉcรฉdemment.")); | |
| } else { | |
| const blockRegex = /```(javascript|js|python|py|bash|sh)?\n([\s\S]*?)```/; | |
| const match = lastAssistantResponse.match(blockRegex); | |
| if (match) { | |
| const lang = match[1] || 'js'; | |
| const code = match[2]; | |
| console.log(chalk.yellow(`Exรฉcution du bloc de code dรฉtectรฉ (${lang})...`)); | |
| await executeLocalCode(lang, code); | |
| } else { | |
| console.log(chalk.red("Aucun bloc de code markdown trouvรฉ.")); | |
| } | |
| } | |
| } else { | |
| const lang = cleanArgs[0]; | |
| const code = cleanArgs.slice(1).join(' '); | |
| await executeLocalCode(lang, code); | |
| } | |
| break; | |
| case '/exec': | |
| const cmd = cleanArgs.join(' '); | |
| if (!cmd) { | |
| console.log(chalk.red("Spรฉcifiez une commande ร exรฉcuter.")); | |
| } else { | |
| console.log(chalk.cyan(`Exรฉcution de la commande : ${cmd}`)); | |
| await handleToolExecution('run_command', { command: cmd }); | |
| } | |
| break; | |
| case '/shell': | |
| console.log(chalk.yellow("Lancement du terminal interactif (tapez 'exit' pour quitter le sous-shell)...")); | |
| try { | |
| execSync('bash', { stdio: 'inherit' }); | |
| } catch (e) {} | |
| break; | |
| case '/repl': | |
| const rlang = cleanArgs[0] || 'node'; | |
| console.log(chalk.yellow(`Lancement du REPL ${rlang}...`)); | |
| try { | |
| execSync(rlang, { stdio: 'inherit' }); | |
| } catch (e) {} | |
| break; | |
| case '/eval': | |
| const expr = cleanArgs.join(' '); | |
| try { | |
| const res = eval(expr); | |
| console.log(chalk.green(`Rรฉsultat : ${res}`)); | |
| } catch (e) { | |
| console.log(chalk.red(`Erreur d'รฉvaluation : ${e.message}`)); | |
| } | |
| break; | |
| case '/sandbox': | |
| if (cleanArgs[0] === 'on') { | |
| sessionConfig.sandbox = true; | |
| console.log(chalk.green("Bac ร sable activรฉ (simulรฉ).")); | |
| } else { | |
| sessionConfig.sandbox = false; | |
| console.log(chalk.green("Bac ร sable dรฉsactivรฉ.")); | |
| } | |
| break; | |
| case '/output': | |
| if (cleanArgs[0] === 'clear') { | |
| console.log(chalk.green("Sortie nettoyรฉe.")); | |
| } else { | |
| console.log(chalk.gray("Aucune sortie rรฉcente enregistrรฉe en dehors du terminal.")); | |
| } | |
| break; | |
| // --- 7. Plugins & outils | |
| case '/tools': | |
| console.log(chalk.cyan("Outils d'interaction locaux disponibles :")); | |
| tools.forEach(t => console.log(` - ${t.function.name} : ${t.function.description}`)); | |
| break; | |
| case '/tool': | |
| if (cleanArgs[0] === 'info') { | |
| const name = cleanArgs[1]; | |
| const tool = tools.find(t => t.function.name === name); | |
| if (tool) { | |
| console.log(chalk.cyan(`Outil [${name}] :`), tool.function.description); | |
| } else { | |
| console.log(chalk.red("Outil introuvable.")); | |
| } | |
| } else { | |
| console.log(chalk.yellow("Les outils fondamentaux de Cypher Coder sont activรฉs par dรฉfaut pour assurer son autonomie.")); | |
| } | |
| break; | |
| case '/plugin': | |
| console.log(chalk.cyan("Aucun plugin externe installรฉ.")); | |
| break; | |
| case '/web': | |
| if (cleanArgs[0] === 'search') { | |
| const q = cleanArgs.slice(1).join(' '); | |
| console.log(chalk.cyan(`Recherche en ligne pour : "${q}"`)); | |
| const res = callApiViaCurl([ | |
| { role: "system", content: "Fais une recherche web et renvoie les rรฉsultats." }, | |
| { role: "user", content: q } | |
| ], []); | |
| console.log(res.content); | |
| } else if (cleanArgs[0] === 'fetch') { | |
| const url = cleanArgs[1]; | |
| console.log(chalk.cyan(`Rรฉcupรฉration de l'URL : ${url}...`)); | |
| const res = callApiViaCurl([ | |
| { role: "system", content: "Rรฉcupรจre le contenu de cette URL et synthรฉtise-la." }, | |
| { role: "user", content: url } | |
| ], []); | |
| console.log(res.content); | |
| } | |
| break; | |
| // --- 8. Affichage & formatting | |
| case '/theme': | |
| if (cleanArgs[0] === 'list') { | |
| console.log("Thรจmes : dark (par dรฉfaut), light"); | |
| } else if (cleanArgs[0] === 'light') { | |
| sessionConfig.theme = 'light'; | |
| console.log(chalk.green("Thรจme light configurรฉ.")); | |
| } else { | |
| sessionConfig.theme = 'dark'; | |
| console.log(chalk.green("Thรจme dark configurรฉ.")); | |
| } | |
| break; | |
| case '/format': | |
| const fmt = cleanArgs[0]; | |
| if (['md', 'plain', 'json'].includes(fmt)) { | |
| sessionConfig.format = fmt; | |
| console.log(chalk.green(`Format des rรฉponses : ${fmt}`)); | |
| } else { | |
| console.log(chalk.red("Formats valides : md, plain, json")); | |
| } | |
| break; | |
| case '/wrap': | |
| case '/verbose': | |
| case '/silent': | |
| case '/color': | |
| const setting = commandName.slice(1); | |
| if (cleanArgs[0] === 'on' || cleanArgs[0] === 'true') { | |
| sessionConfig[setting] = true; | |
| console.log(chalk.green(`Option ${setting} activรฉe.`)); | |
| } else { | |
| sessionConfig[setting] = false; | |
| console.log(chalk.green(`Option ${setting} dรฉsactivรฉe.`)); | |
| } | |
| break; | |
| case '/lang': | |
| sessionConfig.lang = cleanArgs[0] || 'fr'; | |
| console.log(chalk.green(`Langue configurรฉe : ${sessionConfig.lang}`)); | |
| break; | |
| case '/font': | |
| console.log(chalk.gray("Option disponible sur terminaux compatibles uniquement.")); | |
| break; | |
| // --- 9. Config & credentials | |
| case '/config': | |
| if (cleanArgs[0] === 'set') { | |
| const key = cleanArgs[1]; | |
| const val = cleanArgs[2]; | |
| if (key in sessionConfig) { | |
| sessionConfig[key] = val; | |
| console.log(chalk.green(`Configuration ${key} mise ร jour.`)); | |
| } else { | |
| console.log(chalk.red("Clรฉ introuvable.")); | |
| } | |
| } else if (cleanArgs[0] === 'reset') { | |
| sessionConfig.model = "Qwen/Qwen2.5-Coder-32B-Instruct"; | |
| sessionConfig.temperature = 0.7; | |
| sessionConfig.max_tokens = 2048; | |
| console.log(chalk.green("Configuration rรฉinitialisรฉe.")); | |
| } else { | |
| console.log(chalk.cyan("Configuration en cours :"), sessionConfig); | |
| } | |
| break; | |
| case '/api': | |
| console.log(chalk.green("Authentification gรฉrรฉe via variable d'environnement HF_TOKEN ou secret d'Espace.")); | |
| break; | |
| case '/env': | |
| if (cleanArgs[0] === 'set') { | |
| const key = cleanArgs[1]; | |
| const val = cleanArgs[2]; | |
| sessionConfig.env[key] = val; | |
| console.log(chalk.green(`Variable d'environnement locale dรฉfinie: ${key}=${val}`)); | |
| } else { | |
| console.log(chalk.cyan("Variables d'environnement de l'agent :"), sessionConfig.env); | |
| } | |
| break; | |
| // --- 10. Monitoring & debug | |
| case '/debug': | |
| if (cleanArgs[0] === 'on') { | |
| sessionConfig.verbose = true; | |
| console.log(chalk.green("Mode debug/verbose activรฉ.")); | |
| } else { | |
| sessionConfig.verbose = false; | |
| console.log(chalk.green("Mode debug/verbose dรฉsactivรฉ.")); | |
| } | |
| break; | |
| case '/log': | |
| if (cleanArgs[0] === 'clear') { | |
| logs = []; | |
| console.log(chalk.green("Logs locaux effacรฉs.")); | |
| } else if (cleanArgs[0] === 'save') { | |
| const file = cleanArgs[1] || 'cypher_agent.log'; | |
| fs.writeFileSync(file, logs.join('\n'), 'utf8'); | |
| console.log(chalk.green(`Logs exportรฉs dans ${file}`)); | |
| } else { | |
| console.log(chalk.yellow("\n=== Logs rรฉcents de l'agent ===")); | |
| logs.slice(-20).forEach(l => console.log(l)); | |
| console.log("===============================\n"); | |
| } | |
| break; | |
| case '/benchmark': | |
| console.log(chalk.cyan("Lancement du benchmark de l'API Hugging Face...")); | |
| const start = Date.now(); | |
| try { | |
| callApiViaCurl([{ role: "user", content: "Dis hello" }], []); | |
| console.log(chalk.green(`Rรฉussi ! Temps de latence aller-retour : ${Date.now() - start}ms`)); | |
| } catch (e) { | |
| console.log(chalk.red(`รchec du benchmark : ${e.message}`)); | |
| } | |
| break; | |
| case '/ping': | |
| console.log(chalk.cyan("Ping de la passerelle API...")); | |
| try { | |
| const startPing = Date.now(); | |
| execSync("curl -sI https://theshellmaster-cypher-coder.hf.space/ | head -n 1"); | |
| console.log(chalk.green(`Connectivitรฉ OK (${Date.now() - startPing}ms)`)); | |
| } catch (e) { | |
| console.log(chalk.red("Erreur de connexion.")); | |
| } | |
| break; | |
| case '/stats': | |
| console.log(chalk.cyan(`\n=== Statistiques de la session ===`)); | |
| console.log(` Messages dans la conversation : ${chatMessages.length}`); | |
| console.log(` Fichiers chargรฉs en contexte : ${loadedFiles.length}`); | |
| console.log(` Commandes tapรฉes : ${commandHistory.length}`); | |
| console.log(` Nombre d'รฉvรฉnements logguรฉs : ${logs.length}\n`); | |
| break; | |
| case '/trace': | |
| console.log(chalk.cyan("Dernier appel :"), logs[logs.length - 1] || "Aucun appel tracรฉ."); | |
| break; | |
| case '/inspect': | |
| const vname = cleanArgs[0]; | |
| if (vname === 'chatMessages') console.log(chatMessages); | |
| else if (vname === 'loadedFiles') console.log(loadedFiles); | |
| else console.log(sessionConfig); | |
| break; | |
| // --- 11. Automatisation & scripting | |
| case '/macro': | |
| if (cleanArgs[0] === 'save') { | |
| const name = cleanArgs[1]; | |
| macros[name] = [...commandHistory]; | |
| console.log(chalk.green(`Historique des commandes sauvegardรฉ dans la macro '${name}'.`)); | |
| } else if (cleanArgs[0] === 'run') { | |
| const name = cleanArgs[1]; | |
| if (macros[name]) { | |
| console.log(chalk.yellow(`Exรฉcution de la macro : ${name}`)); | |
| for (const cmd of macros[name]) { | |
| if (!cmd.startsWith('/macro')) { | |
| await handleSlashCommand(cmd); | |
| } | |
| } | |
| } else { | |
| console.log(chalk.red("Macro introuvable.")); | |
| } | |
| } else if (cleanArgs[0] === 'list') { | |
| console.log(chalk.cyan("Macros disponibles :"), Object.keys(macros)); | |
| } else if (cleanArgs[0] === 'delete') { | |
| delete macros[cleanArgs[1]]; | |
| console.log(chalk.green(`Macro '${cleanArgs[1]}' supprimรฉe.`)); | |
| } | |
| break; | |
| case '/pipe': | |
| console.log(chalk.yellow("Chaรฎnage d'outils simulรฉ.")); | |
| break; | |
| case '/loop': | |
| const times = parseInt(cleanArgs[0], 10); | |
| const cmdToLoop = cleanArgs.slice(1).join(' '); | |
| if (!isNaN(times) && cmdToLoop) { | |
| for (let idx = 0; idx < times; idx++) { | |
| console.log(chalk.cyan(`[Boucle ${idx+1}/${times}] Exรฉcution...`)); | |
| await handleSlashCommand(cmdToLoop); | |
| } | |
| } | |
| break; | |
| case '/schedule': | |
| case '/watch': | |
| case '/batch': | |
| console.log(chalk.yellow("Fonctionnalitรฉ planifiรฉe pour la prochaine version stable de Cypher Coder.")); | |
| break; | |
| default: | |
| console.log(chalk.red(`Commande slash inconnue: ${commandName}. Tapez /help pour afficher l'aide.`)); | |
| break; | |
| } | |
| return true; | |
| } | |
| // Code runner helper | |
| async function executeLocalCode(lang, code) { | |
| let cmd = ""; | |
| if (lang === 'javascript' || lang === 'js' || lang === 'node') { | |
| cmd = `node -e "${code.replace(/"/g, '\\"')}"`; | |
| } else if (lang === 'python' || lang === 'py' || lang === 'python3') { | |
| cmd = `python3 -c "${code.replace(/"/g, '\\"')}"`; | |
| } else if (lang === 'bash' || lang === 'sh') { | |
| cmd = code; | |
| } else { | |
| console.log(chalk.red(`Langage de code non pris en charge pour l'exรฉcution automatique: ${lang}`)); | |
| return; | |
| } | |
| console.log(chalk.yellow(`Lancement du code local...`)); | |
| await handleToolExecution('run_command', { command: cmd }); | |
| } | |
| async function askQuestion() { | |
| const username = os.userInfo().username || "local-user"; | |
| const { userInput } = await inquirer.prompt([ | |
| { | |
| type: 'input', | |
| name: 'userInput', | |
| message: theme.user(`โฏ ${username} : `), | |
| prefix: '' | |
| } | |
| ]); | |
| const text = userInput.trim(); | |
| if (!text) { | |
| return askQuestion(); | |
| } | |
| const time = new Date().toTimeString().split(' ')[0]; | |
| console.log(theme.border(` โ [timestamp ${time}]`)); | |
| if (text.startsWith('/')) { | |
| const handled = await handleSlashCommand(text); | |
| if (handled) { | |
| return askQuestion(); | |
| } | |
| } | |
| lastUserInput = text; | |
| commandHistory.push(text); | |
| chatMessages.push({"role": "user", "content": text}); | |
| await runAgentTurn(); | |
| askQuestion(); | |
| } | |
| async function main() { | |
| const username = os.userInfo().username || "local-user"; | |
| const model = sessionConfig.model; | |
| const sessionId = `sess_${Math.random().toString(36).substring(2, 10)}`; | |
| console.log(BANNER); | |
| console.log(theme.agent(" CYPHER CODER CLI โ L'IA experte en developpement local")); | |
| console.log(theme.agent(` Cree par DJAKOUA KWANKAM โ Institut Universitaire de Technologie de Douala (IUT)`)); | |
| console.log(theme.border(" โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ")); | |
| console.log(theme.info(` Connecte en tant que : @${username}`)); | |
| console.log(theme.info(` Modele actif : ${model}`)); | |
| console.log(theme.info(` Session : ${sessionId}`)); | |
| console.log(theme.border(" โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ")); | |
| console.log(theme.command(" Tape /help pour voir les commandes disponibles.\n")); | |
| // Initialiser la session de chat | |
| initChat(); | |
| // Support des arguments directs (ex: cypher "Bonjour" ou cypher "/help") | |
| const args = process.argv.slice(2); | |
| if (args.length > 0) { | |
| const initialRequest = args.join(" "); | |
| const time = new Date().toTimeString().split(' ')[0]; | |
| console.log(theme.user(`โฏ ${username} : `) + initialRequest); | |
| console.log(theme.border(` โ [timestamp ${time}]`)); | |
| if (initialRequest.startsWith('/')) { | |
| await handleSlashCommand(initialRequest); | |
| } else { | |
| lastUserInput = initialRequest; | |
| commandHistory.push(initialRequest); | |
| chatMessages.push({"role": "user", "content": initialRequest}); | |
| await runAgentTurn(); | |
| } | |
| } | |
| askQuestion(); | |
| } | |
| main(); | |