cypher-coder / index.js
TheShellMaster's picture
Upload folder using huggingface_hub
b1ebab7 verified
Raw
History Blame
77.2 kB
#!/usr/bin/env node
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();