fix: fix some ui displays and features miss implemented

This commit is contained in:
2026-06-06 16:15:19 +02:00
parent 9736c42424
commit 2332b7f815
22 changed files with 1599 additions and 14 deletions

View File

@ -6,6 +6,8 @@
> Architecture **Hexagonale (Ports & Adapters)** + **SOLID**, stricte.
>
> Stack non négociable : Tauri v2 (shell) · Rust (cœur hexagonal) · TypeScript + React (UI) · xterm.js + portable-pty (terminaux) · git2/libgit2 · russh/ssh2 · wsl.exe.
>
> **Principe fondateur** : IdeA est un IDE 100 % IA dont le rôle est de **refléter fidèlement la façon dont on travaille avec des IAs** — sans jamais dépendre des commandes, flags ou conventions d'un modèle en particulier. Les deux abstractions de premier rang sont les **Agents** (instances IA à rôle/contexte définis) et les **Skills** (workflows réutilisables). Ces deux concepts sont gérés par IdeA de façon universelle : un utilisateur qui passe de Claude Code à Gemini CLI ou Codex retrouve exactement les mêmes Agents et Skills — seul le moteur d'exécution change.
---
@ -134,7 +136,7 @@ Workspace 1───* Window 1───* Tab 1───1 Project
- Invariants : `version` **monotone croissante** ; toute modification du `content_md``version + 1` (voir §8).
**`AgentProfile`** (entité de config runtime IA — le port `AgentRuntime` est paramétré par elle)
- Champs : `id`, `name`, `command: String`, `args: Vec<String>`, `context_injection: ContextInjection`, `detect: Option<String>`, `cwd_template: String` (ex. `"{projectRoot}"`).
- Champs : `id`, `name`, `command: String`, `args: Vec<String>`, `context_injection: ContextInjection`, `detect: Option<String>`, `cwd_template: String` (vaut toujours `"{agentRunDir}"` — voir §9.1 et §14.1).
- Invariants : `command` non vide ; cohérence de `ContextInjection` (voir VO ci-dessous).
**`ContextInjection`** (VO, enum — cœur du moteur IA flexible)
@ -177,7 +179,12 @@ RemoteRef =
- `Tab` = onglet ⇔ **un `Project`** (1:1).
- Invariants : un `Project` ouvert apparaît dans **exactement un** `Tab` à la fois (le drag déplace, ne duplique pas) ; un `Window` a ≥ 1 `Tab` ou est fermée.
**`DomainEvent`** (enum) — `ProjectCreated`, `AgentLaunched`, `AgentExited`, `TemplateUpdated`, `AgentDriftDetected`, `LayoutChanged`, `RemoteConnected`, `GitStateChanged`, `PtyOutput{session_id, bytes}` (ce dernier souvent court-circuité vers un Channel).
**`Skill`** (entité)
- Champs : `id`, `name`, `content_md: MarkdownDoc`, `scope: SkillScope` (`Global` | `Project`).
- Invariants : `name` non vide ; `content_md` non vide.
- Un agent référence 0..N skills (dans l'`AgentManifest`). Les skills assignés sont injectés dans son convention file à l'activation.
**`DomainEvent`** (enum) — `ProjectCreated`, `AgentLaunched`, `AgentExited`, `TemplateUpdated`, `AgentDriftDetected`, `SkillAssigned`, `LayoutChanged`, `RemoteConnected`, `GitStateChanged`, `PtyOutput{session_id, bytes}`, `OrchestratorRequest{requester_id, action}` (ce dernier souvent court-circuité vers un Channel).
---
@ -451,11 +458,19 @@ drift(agent) =
│ ├── agents.json # AgentManifest (mapping md ↔ template ↔ sync ↔ version)
│ ├── layout.json # LayoutTree de l'onglet (sérialisé)
│ ├── project.json # méta projet local (nom, profil par défaut, remote ref)
── agents/
├── reviewer.md # contexte d'un agent de projet
├── backend-dev.md
── agents/
├── reviewer.md # contexte d'un agent de projet
├── backend-dev.md
│ │ └── ...
│ ├── skills/
│ │ ├── code-review.md # contexte d'un skill (voir §14.2)
│ │ ├── simplify.md
│ │ └── ...
│ └── run/
│ ├── <agent-id>/ # cwd isolé par agent actif (créé à l'activation)
│ │ └── CLAUDE.md # fichier de convention généré par IdeA (profil-dépendant)
│ └── ...
└── (CLAUDE.md / AGENTS.md / GEMINI.md générés/symlinkés à l'activation si conventionFile)
└── (aucun CLAUDE.md/AGENTS.md/GEMINI.md à la racine — jamais — voir §14.1)
```
**Schéma `agents.json`** :
@ -504,6 +519,8 @@ Emplacement résolu via Tauri path API (`AppData`/`~/.local/share/IdeA`/`~/Libra
**Formats** : contextes & templates en **Markdown** ; tout le reste en **JSON** (serde). Pas de base de données : fichiers plats, simples, diffables, portables (AppImage friendly).
> **Note** : `.ideai/run/` contient des répertoires d'exécution éphémères (créés à l'activation, nettoyés à la fermeture). Leur contenu (convention files générés) ne doit **pas** être versionné dans git — ajouter `.ideai/run/` au `.gitignore` du projet.
---
## 10. Arborescence du repo
@ -581,6 +598,73 @@ IdeA/
| L9 | **Remote (SSH + WSL)** | `RemoteHost` stratégie, `SshHost`/`WslHost`, adapters FS/PTY/Spawner distants, `RemoteGitRepository`. UI connexion. | `infrastructure/remote`, `application/remote`, `frontend/features/remote` |
| L10 | **Fenêtres & multi-window** | `Workspace`/`Window`/`Tab`, `MoveTabToNewWindow`, drag d'onglet → nouvelle fenêtre OS Tauri. | `application`, `app-tauri`, `frontend/app` |
| L11 | **Packaging & livraison** | Tauri bundle : NSIS `setup.exe`, **AppImage** multi-distro, CI Linux+Windows. | `app-tauri`, CI |
| L12 | **Skills** | Entité `Skill`, `SkillStore`, CRUD skills global+projet, assignation agent↔skills, injection dans convention file à l'activation. UI onglet Skills. | `domain/skill`, `application/skill`, `infrastructure/store`, `frontend/features/skills` |
| L13 | **OrchestratorApi** | File-watcher `.ideai/requests/`, port `OrchestratorApi`, adapter `FsOrchestratorAdapter`, actions `spawn_agent`/`stop_agent`/`update_agent_context`. | `infrastructure/orchestrator`, `application/agent`, `app-tauri` |
---
## 14. Décisions d'architecture figées (2026-06-06)
### 14.1 Isolation du cwd par agent — résolution de la collision de contexte
**Problème** : plusieurs agents du même profil (ex. deux instances Claude Code) sur le même project root produisaient une collision — le fichier de convention (`CLAUDE.md`, `AGENTS.md`…) est un emplacement fixe unique à la racine.
**Décision** : le cwd du PTY d'un agent n'est **jamais** le project root. C'est `.ideai/run/<agent-id>/`, un dossier créé par IdeA à l'activation et nettoyé à la fermeture.
**Convention file généré par IdeA** : IdeA écrit dans ce dossier le fichier conventionnel attendu par le profil (`CLAUDE.md`, `AGENTS.md`, etc.). Ce fichier contient :
1. La **persona/rôle** de l'agent (son `.md` dans `.ideai/agents/`).
2. Le **chemin absolu du project root** (pour que l'agent sache où opérer).
3. Les **skills actifs** assignés à cet agent (voir §14.2).
4. Une référence au **contexte projet partagé** si présent.
**Avantages** :
- Zéro collision entre agents, même N instances du même profil.
- Universel : fonctionne pour toute CLI qui lit un fichier de convention depuis son cwd — aucun flag ou commande propre à un modèle.
- Zéro dépendance à git (git est optionnel — supprimer un repo ne casse rien).
**Impact sur `AgentProfile.cwd_template`** : la valeur est toujours `"{agentRunDir}"`, jamais `"{projectRoot}"`. La connaissance du project root passe par le *contenu* du convention file, pas par le cwd.
---
### 14.2 Skills — abstraction universelle de workflows réutilisables
**Définition** : un **Skill** est un workflow/comportement réutilisable qu'on peut assigner à un agent. Exemples : `code-review`, `simplify`, `run-tests`, `explain`. C'est l'équivalent universel des slash-commands de Claude Code — mais sans dépendance à la syntaxe `/command` d'un modèle particulier.
**Stockage** :
- Skills globaux (templates) : `<app_data>/IdeA/skills/` (store global IDE, réutilisables entre projets).
- Skills de projet : `.ideai/skills/<skill-name>.md` (spécifiques au projet).
**Injection** : les skills assignés à un agent sont **inclus dans son convention file** généré par IdeA au moment de l'activation. L'agent reçoit donc ses skills comme du contexte textuel — aucun mécanisme CLI propriétaire.
**Entité `Skill`** (à ajouter au domaine) :
- Champs : `id`, `name`, `content_md: MarkdownDoc`, `scope: SkillScope` (`Global` | `Project`).
- Un agent peut avoir 0..N skills assignés (stocké dans l'`AgentManifest`).
**Port `SkillStore`** : CRUD skills globaux + skills projet (compose `FileSystem`/store global selon le scope).
---
### 14.3 OrchestratorApi — spawn d'agents depuis un agent ou depuis l'UI
**Objectif** : qu'un agent orchestrateur puisse demander à IdeA de créer un nouvel agent (visible dans la grille et dans l'onglet Agents), exactement comme le ferait l'utilisateur via l'UI.
**Mécanisme** : file-watching sur `.ideai/requests/<requester-id>/`. L'orchestrateur écrit un fichier JSON de requête :
```json
{ "action": "spawn_agent", "name": "dev-backend", "profile": "claude-code", "context": "agents/dev-backend.md" }
```
IdeA détecte le fichier, exécute la même logique que `LaunchAgent` déclenché depuis l'UI, crée la cellule terminal, inscrit l'agent dans l'onglet Agents, puis supprime le fichier et écrit une réponse.
**Règle** : l'orchestrateur ne spawne jamais lui-même un process CLI — il **délègue à IdeA**. IdeA reste l'unique source de vérité du cycle de vie des agents.
**Port `OrchestratorApi`** (adapter entrant, driven by file-watcher) : surveille `.ideai/requests/`, désérialise les commandes, les traduit en appels de use cases (`LaunchAgent`, `StopAgent`…). Implémenté dans `infrastructure/orchestrator`.
**Actions supportées (v1)** : `spawn_agent`, `stop_agent`, `update_agent_context`.
---
### 14.4 Git = intégration optionnelle, zéro dépendance fonctionnelle
Git est un **outil posé par-dessus l'IDE**, pas un socle. Supprimer le repo git d'un projet ne doit casser aucune feature d'IdeA (agents, terminaux, layout, skills, orchestration). Les use cases git (L8) sont un module indépendant ; rien d'autre n'en dépend. Cette contrainte s'applique à toute future décision de conception.
---
@ -591,7 +675,7 @@ IdeA/
3. **Drag d'onglet entre fenêtres Tauri** : Tauri v2 multi-webview/multi-window + DnD natif inter-fenêtres est délicat (le DnD HTML ne traverse pas les fenêtres OS). **Spike** : protocole « detach » (créer une `WebviewWindow`, transférer l'état via store + event, fermer l'onglet source). L10.
4. **Git sur FS distant** : libgit2 ne lit pas un FS SSH/WSL directement. Décision : **fallback git CLI** (`RemoteGitRepository`) côté distant via `ProcessSpawner`. À valider (perf, parsing). L9.
5. **Synchro temps réel UI ↔ PTY** : volume d'octets élevé ; backpressure des Channels Tauri, throttling/coalescing côté front. **Spike** L3.
6. **Injection `conventionFile`** : symlink vs copie du `.md` vers `CLAUDE.md`/`AGENTS.md` ; conflits si fichier existant, .gitignore, droits Windows (symlinks). À cadrer L6.
6. ~~**Injection `conventionFile`** : symlink vs copie du `.md` vers `CLAUDE.md`/`AGENTS.md` ; conflits si fichier existant, .gitignore, droits Windows (symlinks).~~ **Résolu (§14.1)** : cwd isolé par agent dans `.ideai/run/<id>/` — plus de conflit à la racine, convention file généré par copie simple.
7. **SSH auth** : agent/clé/mot de passe/known_hosts ; choix russh (rustls) vs ssh2 (libssh2/OpenSSL — impacte point 2). Décision à figer début L9.
8. **WSL chemins** : conversion `/mnt/c/...``\\wsl$\...`, distros multiples, perf I/O cross-boundary. Spike L9.
9. **Détection d'édition hors-app** des `.md`/templates (content hash) et résolution de conflit lors du sync. L7.