33800 Docs

← Retour

Proposition : Detection outil manquant + Actions d'installation tracees

Date : 03/02/2026 Status : REPORTEE AU BACKLOG Projet : connectors-api + connectors-front Priorite : MOYENNE (amelioration UX, pas bloquant) Prerequis : Fix PowerShell wrapping (commit e9f5f2f) deploye

Concept

Quand une commande SSH echoue parce qu'un outil n'est pas installe :

  1. Detection deterministe du nom de l'outil manquant (code, pas IA)
  2. Proposition d'une commande d'installation adaptee au package manager de la machine
  3. L'utilisateur valide avant execution (jamais automatique)
  4. L'installation est sauvegardee comme action avec tag install
  5. Historique : on sait exactement ce qui a ete installe/desinstalle, quand, sur quelle machine

Architecture

Phase 1 : Detection deterministe (backend)

Nouveau fichier src/services/packageDetector.ts :

interface MissingToolDetection {
  detected: boolean;
  tool_name: string | null;
  install_commands: InstallCommand[];
}

interface InstallCommand {
  package_manager: string;    // 'apt' | 'yum' | 'dnf' | 'brew' | 'choco' | 'winget' | 'scoop'
  command: string;            // 'apt install -y curl'
  requires_sudo: boolean;
}

Patterns de detection stderr (deterministe, regex) :

Pattern OS Exemple
'xxx' n'est pas reconnu en tant que commande Windows FR 'tr' n'est pas reconnu...
'xxx' is not recognized as an internal or external command Windows EN 'curl' is not recognized...
xxx: command not found Linux jq: command not found
xxx: not found Linux (sh) htop: not found
bash: xxx: No such file or directory Linux bash: foo: No such file or directory
The term 'xxx' is not recognized as the name of a cmdlet PowerShell The term 'jq' is not recognized...

Detection package manager (une commande which/where par instance, cachee) :

OS Commande Package managers
Linux which apt dnf yum brew 2>/dev/null apt, dnf, yum, brew
Windows where choco winget scoop 2>nul choco, winget, scoop

Le resultat est cache dans token_metadata de l'instance (comme os_type).

Mapping outil → package (table statique, extensible) :

const TOOL_PACKAGES: Record<string, Record<string, string>> = {
  // tool_name → { package_manager: package_name }
  'jq':     { apt: 'jq', yum: 'jq', dnf: 'jq', brew: 'jq', choco: 'jq', winget: 'jqlang.jq', scoop: 'jq' },
  'curl':   { apt: 'curl', yum: 'curl', choco: 'curl', winget: 'cURL.cURL', scoop: 'curl' },
  'htop':   { apt: 'htop', yum: 'htop', dnf: 'htop', brew: 'htop' },
  'tree':   { apt: 'tree', yum: 'tree', choco: 'tree', scoop: 'tree' },
  'git':    { apt: 'git', yum: 'git', choco: 'git', winget: 'Git.Git', scoop: 'git' },
  'wget':   { apt: 'wget', yum: 'wget', choco: 'wget', winget: 'JernejSimoncic.Wget', scoop: 'wget' },
  'nano':   { apt: 'nano', yum: 'nano', choco: 'nano' },
  'vim':    { apt: 'vim', yum: 'vim', brew: 'vim', choco: 'vim' },
  'python3':{ apt: 'python3', yum: 'python3', brew: 'python', choco: 'python', winget: 'Python.Python.3' },
  'node':   { apt: 'nodejs', yum: 'nodejs', brew: 'node', choco: 'nodejs', winget: 'OpenJS.NodeJS' },
  'docker': { apt: 'docker.io', yum: 'docker', brew: 'docker', choco: 'docker-desktop', winget: 'Docker.DockerDesktop' },
  'ffmpeg': { apt: 'ffmpeg', yum: 'ffmpeg', brew: 'ffmpeg', choco: 'ffmpeg', winget: 'Gyan.FFmpeg', scoop: 'ffmpeg' },
  '7z':     { apt: 'p7zip-full', yum: 'p7zip', choco: '7zip', winget: '7zip.7zip', scoop: '7zip' },
  // ... extensible
};

Phase 2 : Integration dans le flow AI suggest (backend)

Dans POST /api/ai/test-command, apres execution :

// Si la commande a echoue, detecter outil manquant
if (!result.success && result.stderr) {
  const detection = packageDetector.detect(result.stderr, instanceId, userId);
  if (detection.detected) {
    return {
      ...result,
      missing_tool: {
        name: detection.tool_name,
        install_commands: detection.install_commands
      }
    };
  }
}

Le frontend recoit missing_tool dans la reponse et peut proposer l'installation.

Phase 3 : Actions d'installation (frontend + backend)

Frontend : Quand missing_tool est present dans la reponse test :

┌──────────────────────────────────────────────────┐
│  ⚠ Outil manquant : jq                          │
│                                                   │
│  Commande d'installation suggeree :               │
│  ┌──────────────────────────────────────────────┐ │
│  │ sudo apt install -y jq                       │ │
│  └──────────────────────────────────────────────┘ │
│                                                   │
│  [Installer]  [Ignorer]  [Sauver comme action]   │
│                                                   │
└──────────────────────────────────────────────────┘

3 choix :

Backend : L'action d'installation est une action SSH classique avec :

{
  "name": "Install jq",
  "action_type": "ssh",
  "instance_id": "xxx",
  "config": {
    "type": "command",
    "command": "sudo apt install -y jq",
    "output_parser": "raw"
  },
  "tags": ["install", "package-management"],
  "input_schema": null
}

Phase 4 : Inventaire logiciel par instance

Consultation : Page instance → onglet "Packages" ou section dans la page existante.

Filtre les actions par tags contains 'install' + instance_id → affiche :

Package Date Status Commande
jq 03/02/2026 14:30 OK sudo apt install -y jq
htop 03/02/2026 14:35 OK sudo apt install -y htop
tree 03/02/2026 15:00 ERREUR sudo apt install -y tree

On sait exactement ce qui a ete installe via notre systeme, avec l'historique d'execution complet (succes, erreur, stdout, stderr, duree).

Desinstallation : Meme principe — bouton "Desinstaller" genere la commande inverse (apt remove, choco uninstall, etc.), cree une action avec tag uninstall.

Fichiers a creer/modifier

Backend (connectors-api)

Fichier Action Description
src/services/packageDetector.ts CREER Detection outil manquant + mapping packages
src/index.ts MODIFIER Enrichir reponse /api/ai/test-command avec missing_tool
src/services/ssh.ts MODIFIER Detecter et cacher le package manager dans token_metadata

Frontend (connectors-front)

Fichier Action Description
src/routes/connectors/instance/[id]/index.tsx MODIFIER Bandeau missing_tool dans le flow AI suggest
src/routes/connectors/instance/[id]/index.tsx MODIFIER Section "Packages installes" (ou onglet)

Pas de migration BDD necessaire

On reutilise les tables existantes :

Phases de livraison

Phase Contenu Dependances
1 packageDetector.ts + enrichissement test-command Aucune
2 Bandeau frontend "outil manquant" + bouton Installer Phase 1
3 Section inventaire packages par instance Phase 2
4 Desinstallation + tags uninstall Phase 3

Points de conception

Limites connues