33800 Docs

← Retour

Proposition: Refonte UX Éditeur de Routines

Status : IMPLEMENTEE

Problèmes actuels

  1. Loop/Condition : Impossible de définir quels nodes sont dans le body vs après
  2. Expressions : Écrire {{nodes.search.output.messages[0].id}} est complexe
  3. Transform : Pas clair quel contexte est disponible
  4. Pas d'aide IA : L'utilisateur doit tout écrire manuellement
  5. Linéaire : L'UI force une vue linéaire alors que c'est un graphe

Vision : Éditeur intelligent

┌─────────────────────────────────────────────────────────────────────────────┐
│  ROUTINE: Gmail non lus                                     [Sauvegarder]   │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  ┌─ TRIGGER ─────────────────────────────────────────────────────────────┐ │
│  │ manual  params: query                                                 │ │
│  └───────────────────────────────────────────────────────────────────────┘ │
│                              │                                              │
│                              ▼                                              │
│  ┌─ ACTION: Recherche Gmail ─────────────────────────────────────────────┐ │
│  │ gmail.message.list  q: {{trigger.params.query}}                       │ │
│  │ Output: messages[]                                          [Config]  │ │
│  └───────────────────────────────────────────────────────────────────────┘ │
│                              │                                              │
│                              ▼                                              │
│  ┌─ LOOP: Pour chaque email ─────────────────────────────────────────────┐ │
│  │ items: {{nodes.search.output.messages}}                               │ │
│  │ ┌──────────────────────────────────────────────────────────────────┐  │ │
│  │ │ BODY (exécuté pour chaque item)                      [+ Node]   │  │ │
│  │ │                                                                  │  │ │
│  │ │   ┌─ ACTION: Détails ──────────────────────────────────────────┐│  │ │
│  │ │   │ gmail.message.get  id: {{loop.item.id}}                    ││  │ │
│  │ │   └────────────────────────────────────────────────────────────┘│  │ │
│  │ │                              │                                  │  │ │
│  │ │   ┌─ TRANSFORM ─────────────────────────────────────────────────┐│  │ │
│  │ │   │ pick: [id, snippet, from]                                  ││  │ │
│  │ │   └────────────────────────────────────────────────────────────┘│  │ │
│  │ └──────────────────────────────────────────────────────────────────┘  │ │
│  └───────────────────────────────────────────────────────────────────────┘ │
│                              │                                              │
│                              ▼                                              │
│  ┌─ OUTPUT ──────────────────────────────────────────────────────────────┐ │
│  │ {{nodes.loop.output}}                                                 │ │
│  └───────────────────────────────────────────────────────────────────────┘ │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘

Fonctionnalités clés

1. Structure visuelle des loops et conditions

Loop :

Condition :

┌─ CONDITION: Has results ───────────────────────────┐
│ {{nodes.search.output.messages.length}} > 0        │
│ ┌─────────────────┐     ┌─────────────────┐        │
│ │  TRUE branch    │     │  FALSE branch   │        │
│ │  [+ Node]       │     │  [+ Node]       │        │
│ └─────────────────┘     └─────────────────┘        │
└────────────────────────────────────────────────────┘

2. Aide IA pour les expressions

Bouton "Ask AI" à côté de chaque champ expression :

┌─ Input mapping ──────────────────────────────────────────────────────┐
│ q: [{{trigger.params.query}}              ] [?] [AI]                 │
│                                                                       │
│ ┌─ AI Assistant ───────────────────────────────────────────────────┐ │
│ │ "Je veux chercher les emails non lus de la dernière semaine"     │ │
│ │                                                    [Générer]     │ │
│ │                                                                   │ │
│ │ Suggestion:                                                       │ │
│ │ is:unread after:{{env.DATE | dateSubtract(7)}}                   │ │
│ │                                               [Appliquer]        │ │
│ └───────────────────────────────────────────────────────────────────┘│
└──────────────────────────────────────────────────────────────────────┘

L'IA a accès à :

3. Context Explorer

Panneau latéral montrant tout ce qui est disponible :

┌─ Contexte disponible ────────────────────┐
│                                          │
│ ▼ trigger                                │
│   └─ params                              │
│       └─ query: string                   │
│                                          │
│ ▼ nodes                                  │
│   ├─ search (action)                     │
│   │   └─ output                          │
│   │       ├─ messages: array [10]        │
│   │       │   └─ [0]                     │
│   │       │       ├─ id: "abc123"        │
│   │       │       └─ threadId: "xyz"     │
│   │       └─ nextPageToken: string       │
│   └─ loop (loop)                         │
│       └─ output: array                   │
│                                          │
│ ▼ variables                              │
│   └─ count: 0                            │
│                                          │
│ ▼ loop (si dans un loop)                 │
│   ├─ item: object                        │
│   │   ├─ id: "abc123"                    │
│   │   └─ threadId: "xyz"                 │
│   └─ index: 0                            │
│                                          │
│ ▼ env                                    │
│   ├─ DATE: "2026-02-03"                  │
│   └─ TIMESTAMP: 1738600000               │
│                                          │
│ [Clic pour insérer dans le champ actif]  │
└──────────────────────────────────────────┘

Click-to-insert : Cliquer sur un élément l'insère dans le champ actuellement focus.

4. Transform Builder visuel

Au lieu d'écrire du JSON, interface visuelle :

┌─ Transform: Extraire infos ─────────────────────────────────────────┐
│                                                                      │
│ Input: [{{nodes.fetch.output}}                    ] [Browse...]     │
│                                                                      │
│ Operations:                                        [+ Operation]     │
│ ┌────────────────────────────────────────────────────────────────┐  │
│ │ 1. [pick ▼]  keys: [id] [snippet] [from] [+]                  │  │
│ │                                                      [×]       │  │
│ └────────────────────────────────────────────────────────────────┘  │
│ ┌────────────────────────────────────────────────────────────────┐  │
│ │ 2. [filter ▼]  key: [from]  [contains ▼]  value: [@gmail]     │  │
│ │                                                      [×]       │  │
│ └────────────────────────────────────────────────────────────────┘  │
│                                                                      │
│ Preview output:                                                      │
│ ┌────────────────────────────────────────────────────────────────┐  │
│ │ [                                                              │  │
│ │   { "id": "abc", "snippet": "Hello...", "from": "x@gmail" }   │  │
│ │ ]                                                              │  │
│ └────────────────────────────────────────────────────────────────┘  │
│                                                                      │
│ [Ask AI: "Je veux garder seulement les emails de Google"]          │
└──────────────────────────────────────────────────────────────────────┘

5. Mode Code (avancé)

Pour les utilisateurs avancés, toggle vers mode JSON brut :

┌─ Transform ──────────────────────── [Visual] [Code] ─┐
│ {                                                    │
│   "input": "{{nodes.fetch.output}}",                │
│   "operations": [                                    │
│     { "type": "pick", "config": { "keys": [...] }}, │
│     { "type": "filter", "config": {...} }           │
│   ]                                                  │
│ }                                                    │
└──────────────────────────────────────────────────────┘

Intégration IA Codegen

Cas d'usage

  1. Écrire une expression : "Je veux l'email du premier message" → {{nodes.search.output.messages[0].payload.headers | find('From').value}}

  2. Créer un transform : "Extraire sujet et date de chaque email" → Génère les operations pick + template

  3. Débugger : "Pourquoi mon loop ne fonctionne pas ?" → Analyse la config et suggère des corrections

  4. Générer une routine complète : "Routine pour archiver les vieux emails" → Génère tous les nodes avec la bonne structure

Endpoint API

POST /api/ai/routine-assist
{
  "routine": { ... },           // Routine actuelle
  "current_node": "transform1", // Node en cours d'édition
  "field": "input",             // Champ focus
  "prompt": "Je veux filtrer par date",
  "context": {                  // Contexte live si dispo
    "nodes.search.output": { ... }
  }
}

Plan d'implémentation

Phase 1 : Structure visuelle (priorité haute)

Phase 2 : Context Explorer

Phase 3 : AI Assistant

Phase 4 : Transform Builder


Questions

  1. Context Explorer : Panneau latéral fixe ou popup au focus ?
  2. AI : Utiliser l'agent codegen existant ou endpoint dédié routines ?
  3. Preview : Faut-il pouvoir "dry run" un node avec des données mock ?

Fichiers à créer/modifier

Nouveaux composants

Modifications

Backend

Estimation : Gros chantier, 3-4 sessions de travail