diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ddccd4..3a512bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,7 @@ Format basé sur [Keep a Changelog](https://keepachangelog.com/fr/1.1.0/), et [Semantic Versioning](https://semver.org/spec/v2.0.0.html). > **En cours de développement** : les changements à venir sont listés dans la section -> [Unreleased](#unreleased). La dernière version livrée est **2.74.0**. +> [Unreleased](#unreleased). La dernière version livrée est **2.75.0**. --- @@ -14,6 +14,24 @@ et [Semantic Versioning](https://semver.org/spec/v2.0.0.html). --- +## [2.75.0] — 2026-10-22 + +### Ajouté + +- **Panneau Spark v2 (#219, Fusion — Lot 1)** — les assets partagés + `frontend/draco-panneau.js` / `frontend/draco-panneau.css` passent + en v2, à l'identique dans les quatre applications : réponses de + l'agent en **Markdown rendu** (HTML produit par le service + d'agents 0.10.0, sanitizé côté serveur), **largeur réglable** + persistée, **thème clair/sombre** aligné sur l'application hôte + (suivi en direct de `html[data-theme]`), et **discussions façon + Muse** — discussion principale perpétuelle et discussions + parallèles créées, archivées, supprimées depuis le tiroir du + panneau. Aucun code propre à ObsiGate n'est modifié ; + redéploiement Docker requis. + +--- + ## [2.74.0] — 2026-10-22 ### Ajouté diff --git a/README.fr.md b/README.fr.md index 92d975a..0274fd8 100644 --- a/README.fr.md +++ b/README.fr.md @@ -4,7 +4,7 @@ **Porte d'entrée web ultra-léger pour vos vaults Obsidian** — Accédez, naviguez et recherchez dans toutes vos notes Obsidian depuis n'importe quel appareil via une interface web moderne et responsive. -[]() +[]() [](https://opensource.org/licenses/MIT) [](https://www.docker.com/) [](https://www.python.org/) @@ -977,8 +977,8 @@ Ce projet est sous licence **MIT** — voir le fichier [LICENSE](LICENSE) pour l ## 📝 Changelog -Consultez le [CHANGELOG.md](./CHANGELOG.md) pour l'historique complet de toutes les versions (v1.0.0 → v2.74.0). +Consultez le [CHANGELOG.md](./CHANGELOG.md) pour l'historique complet de toutes les versions (v1.0.0 → v2.75.0). --- -*Projet : ObsiGate | Version : 2.74.0 | Dernière mise à jour : Septembre 2026* +*Projet : ObsiGate | Version : 2.75.0 | Dernière mise à jour : Septembre 2026* diff --git a/README.md b/README.md index 58fe4e2..e072caf 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ **Ultra-light web gateway for your Obsidian vaults** — Access, browse, and search all your Obsidian notes from any device via a modern, responsive web interface. -[]() +[]() [](https://opensource.org/licenses/MIT) [](https://www.docker.com/) [](https://www.python.org/) @@ -1152,8 +1152,8 @@ This project is licensed under the **MIT License** - see the [LICENSE](LICENSE) ## 📝 Changelog -See [CHANGELOG.md](./CHANGELOG.md) for the complete version history (v1.0.0 → v2.74.0). +See [CHANGELOG.md](./CHANGELOG.md) for the complete version history (v1.0.0 → v2.75.0). --- -*Project: ObsiGate | Version: 2.74.0 | Last updated: September 2026* +*Project: ObsiGate | Version: 2.75.0 | Last updated: September 2026* diff --git a/VERSION b/VERSION index 04b6fa2..ddcb9bf 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.74.0 +2.75.0 diff --git a/desktop/Cargo.lock b/desktop/Cargo.lock index aac3a23..0939222 100644 --- a/desktop/Cargo.lock +++ b/desktop/Cargo.lock @@ -2626,7 +2626,7 @@ dependencies = [ [[package]] name = "obsigate-desktop" -version = "2.74.0" +version = "2.75.0" dependencies = [ "chrono", "env_logger", diff --git a/desktop/Cargo.toml b/desktop/Cargo.toml index 5a521e2..9e4c705 100644 --- a/desktop/Cargo.toml +++ b/desktop/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "obsigate-desktop" -version = "2.74.0" +version = "2.75.0" description = "ObsiGate Desktop — Porte d'entrée native pour vos vaults Obsidian" authors = ["Bruno Charest"] edition = "2021" diff --git a/desktop/tauri.conf.json b/desktop/tauri.conf.json index 228ec59..52391cb 100644 --- a/desktop/tauri.conf.json +++ b/desktop/tauri.conf.json @@ -1,7 +1,7 @@ { "$schema": "https://raw.githubusercontent.com/nicedoc/obsigate/main/desktop/tauri.conf.schema.json", "productName": "ObsiGate", - "version": "2.74.0", + "version": "2.75.0", "identifier": "com.obsigate.desktop", "build": { "frontendDist": "../frontend", diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index f6c3fb8..6b661c0 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -1,6 +1,6 @@ # ObsiGate — Roadmap -> **Version :** 2.74.0 | **Dernière mise à jour :** 2026-10-22 +> **Version :** 2.75.0 | **Dernière mise à jour :** 2026-10-22 > **Ce fichier ne contient que le travail à venir** (🔵 En cours + ⚪ Backlog) et un index compact > vers les fonctionnalités livrées. > - **Méthode de livraison à appliquer pour toute tâche : [DELIVERY_WORKFLOW.md](./DELIVERY_WORKFLOW.md)** @@ -48,6 +48,23 @@ (`backend/main.py`, seul hôte ajouté) - [x] Tests `test_draco_barre.py` (intégration + CSP verrouillées) +### 219. Fusion — panneau Spark v2 (Lot 1) + +- **Effort :** ~0,5 jour | **Impact :** 🟢 | **Ouvert :** 2026-10-22 | **Statut :** 🔵 en cours +- **Fiche :** [features/fusion-panneau-spark-v2-219.md](./features/fusion-panneau-spark-v2-219.md) +- **Description :** le panneau Spark (#218) passe en v2, à l'identique + dans les quatre applications (carte fusion-trois-apps #17) : + réponses de l'agent en **Markdown rendu** (HTML produit par le + service d'agents 0.10.0, sanitizé côté serveur), **largeur + réglable** persistée, **thème clair/sombre aligné** sur + l'application hôte, **discussions façon Muse** (principale + perpétuelle + parallèles créées/archivées/supprimées). Côté + ObsiGate : assets vendangés uniquement, aucun code propre touché. +- **Sous-tâches :** + - [x] Assets `frontend/draco-panneau.js` / `frontend/draco-panneau.css` + remplacés par la v2 partagée du programme + - [x] Fiche de conception `features/fusion-panneau-spark-v2-219.md` + ### 215. Fusion bloc 1 — barre d'apps commune et références croisées des notes - **Effort :** ~1 jour | **Impact :** 🟢 | **Ouvert :** 2026-10-20 | **Statut :** ✅ livré le 2026-10-20 (2.70.0) diff --git a/docs/features/fusion-panneau-spark-v2-219.md b/docs/features/fusion-panneau-spark-v2-219.md new file mode 100644 index 0000000..baacb70 --- /dev/null +++ b/docs/features/fusion-panneau-spark-v2-219.md @@ -0,0 +1,29 @@ +# #219 — Fusion : panneau Spark v2 (Lot 1) + +**Contexte.** Le panneau Spark livré en 2.74.0 (#218) affichait les +réponses de l'agent en texte brut (les `##` et `**` du Markdown +restaient visibles), avait une largeur fixe, un thème clair codé en +dur déconnecté de l'application hôte, et une seule conversation sans +gestion. Le Lot 1 du « Panneau v2 » (carte fusion-trois-apps #17, +arbitrage de Bruno du 2026-10-22) corrige ces quatre points, à +l'identique dans les quatre applications du programme. + +**Livraison (côté ObsiGate : assets vendangés uniquement).** + +- `frontend/draco-panneau.js` / `frontend/draco-panneau.css` + remplacés par la v2 partagée (octet pour octet avec TikTak, + Flowdeck et Kanbante) : + - **Markdown rendu** : les réponses et les rapports de missions + affichent le HTML produit par le service d'agents (0.10.0 : + mistune + sanitizer côté serveur) ; + - **largeur réglable** à la souris (poignée, persistée, + double-clic = largeur par défaut) ; + - **thème clair/sombre aligné** sur l'application hôte + (`html[data-theme]`, ici celui d'ObsiGate, suivi en direct) ; + - **discussions façon Muse** : discussion principale + perpétuelle + discussions parallèles créées, archivées et + supprimées depuis le tiroir du panneau. +- Le travail de fond est dans le service d'agents (agent-commun + 0.10.0) ; ObsiGate ne change aucun code propre. Le `/static` est + déjà servi en `Cache-Control: no-cache` : aucun versionnage + d'asset à ajouter. Redéploiement Docker requis. diff --git a/frontend/draco-panneau.css b/frontend/draco-panneau.css index 743bc07..d337013 100644 --- a/frontend/draco-panneau.css +++ b/frontend/draco-panneau.css @@ -1,83 +1,189 @@ -/* Panneau Spark — branchement au service d'agents (Fusion, jalon J1). - Composant d'intégration TikTak : le panneau définitif sera vendangé - depuis dracodev-commons ; celui-ci prouve le chemin panneau → service. */ +/* Panneau Spark — service d'agents (Fusion, J1 → Panneau v2 Lot 1). + Thème clair/sombre piloté par [data-draco-theme] sur le panneau : + le JS le cale sur le thème de l'app hôte (html[data-theme], repli + prefers-color-scheme) et suit les bascules en direct. Toutes les + couleurs passent par les variables ci-dessous — en-tête et fenêtre + partagent donc toujours le même mode. */ .draco-panneau { - position: fixed; top: 0; right: 0; height: 100dvh; width: 388px; max-width: 94vw; - background: #fbfbfa; color: #242624; z-index: 400; + --p-fond: #fbfbfa; --p-surface: #ffffff; --p-bord: #e4e5e0; + --p-texte: #242624; --p-doux: #6c7268; --p-faint: #8a8f84; + --p-chip: #f4f5f1; --p-chip-bord: #d6d8d1; --p-chip-survol: #e9ebe4; + --p-agent: #eef0ea; --p-champ: #ffffff; --p-code: #e8eae3; + --p-appro-fond: #fdf6ec; --p-danger-fond: #f6e3de; --p-danger: #a03a28; + --p-accent: #7c5cd6; --p-lien: #5b3df0; + position: fixed; top: 0; right: 0; height: 100dvh; width: 388px; max-width: 96vw; + background: var(--p-fond); color: var(--p-texte); z-index: 400; box-shadow: -12px 0 36px rgb(0 0 0 / .22); display: flex; flex-direction: column; transform: translateX(105%); transition: transform .28s ease; font: 14px/1.5 system-ui, "Segoe UI", sans-serif; } +.draco-panneau[data-draco-theme="dark"] { + --p-fond: #17181a; --p-surface: #1f2023; --p-bord: #33353a; + --p-texte: #eceeeb; --p-doux: #a6aba0; --p-faint: #83887e; + --p-chip: #26272b; --p-chip-bord: #3a3c41; --p-chip-survol: #2e3036; + --p-agent: #26272b; --p-champ: #1f2023; --p-code: #2c2e33; + --p-appro-fond: #2a2118; --p-danger-fond: #40241f; --p-danger: #e8a08d; + --p-lien: #b39df5; +} .draco-panneau.open { transform: translateX(0); } +.draco-poignee { + position: absolute; left: 0; top: 0; bottom: 0; width: 8px; + cursor: ew-resize; z-index: 5; touch-action: none; +} +.draco-poignee:hover { background: color-mix(in srgb, var(--p-accent) 35%, transparent); } +@media (max-width: 700px) { .draco-poignee { display: none; } } .draco-panneau-hd { display: flex; align-items: center; gap: 9px; - padding: 13px 15px; border-bottom: 1px solid #e4e5e0; background: #fff; + padding: 13px 15px; border-bottom: 1px solid var(--p-bord); background: var(--p-surface); } .draco-panneau-hd .titre { font-weight: 700; font-size: 15px; } -.draco-panneau-hd .soustitre { font-size: 12px; color: #6c7268; } +.draco-panneau-hd .soustitre { font-size: 12px; color: var(--p-doux); } .draco-panneau-hd .fermer { - margin-left: auto; border: 0; background: #eef0ea; border-radius: 8px; - width: 30px; height: 30px; cursor: pointer; font-size: 14px; + margin-left: auto; border: 0; background: var(--p-agent); color: var(--p-texte); + border-radius: 8px; width: 30px; height: 30px; cursor: pointer; font-size: 14px; } .draco-panneau-etat { display: flex; align-items: center; gap: 7px; font-size: 12.5px; } .draco-panneau-etat .point { width: 9px; height: 9px; border-radius: 50%; background: #b9bdb2; flex: none; } .draco-panneau-etat.ok .point { background: #2ea36b; } .draco-panneau-etat.err .point { background: #cf4b32; } -.draco-panneau-outils { display: flex; gap: 8px; padding: 9px 15px; border-bottom: 1px solid #e4e5e0; background: #fff; } -.draco-panneau-outils button { - border: 1px solid #d6d8d1; background: #f4f5f1; border-radius: 999px; - padding: 5px 12px; font: 600 12.5px system-ui; cursor: pointer; +/* Barre des discussions (façon Muse) */ +.draco-disc-bar { + display: flex; align-items: center; gap: 7px; + padding: 8px 15px; border-bottom: 1px solid var(--p-bord); background: var(--p-surface); } -.draco-panneau-outils button:hover { background: #e9ebe4; } +.draco-disc-bar .d-titre { + flex: 1; font-weight: 600; font-size: 13px; min-width: 0; + white-space: nowrap; overflow: hidden; text-overflow: ellipsis; +} +.draco-disc-bar .d-btn { + border: 1px solid var(--p-chip-bord); background: var(--p-chip); color: var(--p-texte); + border-radius: 999px; padding: 4px 10px; font: 600 12px system-ui; cursor: pointer; flex: none; +} +.draco-disc-bar .d-btn:hover { background: var(--p-chip-survol); } +.draco-discussions { + border-bottom: 1px solid var(--p-bord); background: var(--p-surface); + max-height: 46%; overflow-y: auto; padding: 8px 12px; +} +.draco-discussions .d-section { + font-size: 11px; font-weight: 700; text-transform: uppercase; + letter-spacing: .5px; color: var(--p-doux); margin: 8px 2px 4px; +} +.draco-discussions .d-section:first-child { margin-top: 0; } +.draco-discussions .d-item { + border: 1px solid transparent; border-radius: 9px; padding: 6px 8px; cursor: pointer; +} +.draco-discussions .d-item:hover { background: var(--p-chip); } +.draco-discussions .d-item.actif { border-color: var(--p-accent); background: var(--p-chip); } +.draco-discussions .d-meta { font-weight: 600; font-size: 13px; } +.draco-discussions .d-sous { font-size: 12px; color: var(--p-doux); } +.draco-discussions .d-actions { display: flex; gap: 6px; margin-top: 5px; } +.draco-discussions .d-actions button { + border: 1px solid var(--p-chip-bord); background: var(--p-surface); color: var(--p-texte); + border-radius: 7px; padding: 3px 9px; font: 600 11.5px system-ui; cursor: pointer; +} +.draco-discussions .d-actions button.danger { color: var(--p-danger); border-color: var(--p-danger-fond); } +.draco-discussions .d-vide, .draco-discussions .d-chargement { + font-size: 12.5px; color: var(--p-doux); padding: 2px 8px 6px; +} +.draco-panneau-outils { display: flex; gap: 8px; padding: 9px 15px; border-bottom: 1px solid var(--p-bord); background: var(--p-surface); } +.draco-panneau-outils button { + border: 1px solid var(--p-chip-bord); background: var(--p-chip); color: var(--p-texte); + border-radius: 999px; padding: 5px 12px; font: 600 12.5px system-ui; cursor: pointer; +} +.draco-panneau-outils button:hover { background: var(--p-chip-survol); } .draco-appro { - align-self: stretch; background: #fdf6ec; border: 1.6px solid #e8a13c; + align-self: stretch; background: var(--p-appro-fond); border: 1.6px solid #e8a13c; border-radius: 12px; padding: 10px 12px; } .draco-appro .titre { font-weight: 700; font-size: 12px; color: #9a6a1c; text-transform: uppercase; letter-spacing: .4px; } +.draco-panneau[data-draco-theme="dark"] .draco-appro .titre { color: #e8bc7a; } .draco-appro .resume { margin: 5px 0 8px; } .draco-appro .btns { display: flex; gap: 7px; } -.draco-appro .btns button { border: 0; border-radius: 8px; padding: 6px 11px; font: 600 12.5px system-ui; cursor: pointer; background: #eef0ea; } +.draco-appro .btns button { border: 0; border-radius: 8px; padding: 6px 11px; font: 600 12.5px system-ui; cursor: pointer; background: var(--p-agent); color: var(--p-texte); } .draco-appro .btns button.go { background: #2ea36b; color: #fff; } -.draco-auj { align-self: stretch; background: #fff; border: 1px solid #e4e5e0; border-radius: 12px; padding: 10px 12px; } -.draco-auj h5 { font-size: 12px; text-transform: uppercase; letter-spacing: .4px; color: #6c7268; margin: 6px 0 4px; } +.draco-auj { align-self: stretch; background: var(--p-surface); border: 1px solid var(--p-bord); border-radius: 12px; padding: 10px 12px; } +.draco-auj h5 { font-size: 12px; text-transform: uppercase; letter-spacing: .4px; color: var(--p-doux); margin: 6px 0 4px; } .draco-auj h5:first-child { margin-top: 0; } .draco-auj ul { margin: 0; padding-left: 17px; } -.draco-auj .etat-source { color: #6c7268; font-size: 12.5px; } +.draco-auj .etat-source { color: var(--p-doux); font-size: 12.5px; } .draco-panneau-msgs { flex: 1; overflow-y: auto; padding: 14px 15px; display: flex; flex-direction: column; gap: 9px; } .draco-msg { max-width: 88%; padding: 9px 12px; border-radius: 13px; white-space: pre-wrap; word-wrap: break-word; } .draco-msg.user { align-self: flex-end; background: #2f6fed; color: #fff; border-bottom-right-radius: 4px; } -.draco-msg.agent { align-self: flex-start; background: #eef0ea; border-bottom-left-radius: 4px; } -.draco-msg.sys { align-self: center; background: none; color: #6c7268; font-size: 12.5px; text-align: center; max-width: 96%; } -.draco-panneau-ft { border-top: 1px solid #e4e5e0; padding: 11px 12px; background: #fff; } +.draco-msg.agent { align-self: flex-start; background: var(--p-agent); border-bottom-left-radius: 4px; } +.draco-msg.sys { align-self: center; background: none; color: var(--p-doux); font-size: 12.5px; text-align: center; max-width: 96%; } +.draco-panneau-ft { border-top: 1px solid var(--p-bord); padding: 11px 12px; background: var(--p-surface); } .draco-panneau-form { display: flex; gap: 8px; } .draco-panneau-form input { - flex: 1; border: 1px solid #d6d8d1; border-radius: 10px; padding: 9px 11px; font: inherit; + flex: 1; border: 1px solid var(--p-chip-bord); border-radius: 10px; padding: 9px 11px; + font: inherit; background: var(--p-champ); color: var(--p-texte); } .draco-panneau-form button { - border: 0; border-radius: 10px; background: #7c5cd6; color: #fff; + border: 0; border-radius: 10px; background: var(--p-accent); color: #fff; padding: 9px 14px; font: inherit; font-weight: 600; cursor: pointer; } .draco-panneau-form button:disabled { opacity: .5; cursor: default; } -.draco-panneau-note { font-size: 11.5px; color: #8a8f84; margin-top: 8px; text-align: center; } -.draco-missions { align-self: stretch; background: #fff; border: 1px solid #e4e5e0; border-radius: 12px; padding: 10px 12px; } -.draco-missions h5 { font-size: 12px; text-transform: uppercase; letter-spacing: .4px; color: #6c7268; margin: 0 0 6px; } -.draco-missions label { display: block; font-size: 12px; font-weight: 600; color: #6c7268; margin: 8px 0 3px; } +.draco-panneau-note { font-size: 11.5px; color: var(--p-faint); margin-top: 8px; text-align: center; } +.draco-missions { align-self: stretch; background: var(--p-surface); border: 1px solid var(--p-bord); border-radius: 12px; padding: 10px 12px; } +.draco-missions h5 { font-size: 12px; text-transform: uppercase; letter-spacing: .4px; color: var(--p-doux); margin: 0 0 6px; } +.draco-missions label { display: block; font-size: 12px; font-weight: 600; color: var(--p-doux); margin: 8px 0 3px; } .draco-missions select, .draco-missions input, .draco-missions textarea { - width: 100%; box-sizing: border-box; border: 1px solid #d6d8d1; border-radius: 8px; - padding: 7px 9px; font: inherit; font-size: 13px; background: #fff; + width: 100%; box-sizing: border-box; border: 1px solid var(--p-chip-bord); border-radius: 8px; + padding: 7px 9px; font: inherit; font-size: 13px; background: var(--p-champ); color: var(--p-texte); } .draco-missions .btns { display: flex; gap: 7px; margin-top: 10px; } -.draco-missions .btns button { border: 0; border-radius: 8px; padding: 6px 11px; font: 600 12.5px system-ui; cursor: pointer; background: #eef0ea; } -.draco-missions .btns button.go { background: #7c5cd6; color: #fff; } +.draco-missions .btns button { border: 0; border-radius: 8px; padding: 6px 11px; font: 600 12.5px system-ui; cursor: pointer; background: var(--p-agent); color: var(--p-texte); } +.draco-missions .btns button.go { background: var(--p-accent); color: #fff; } .draco-missions .m-liste { margin-top: 12px; display: flex; flex-direction: column; gap: 8px; } -.draco-missions .etat-source { color: #6c7268; font-size: 12.5px; } -.draco-missions .m-item { border: 1px solid #e4e5e0; border-radius: 10px; padding: 8px 10px; } +.draco-missions .etat-source { color: var(--p-doux); font-size: 12.5px; } +.draco-missions .m-item { border: 1px solid var(--p-bord); border-radius: 10px; padding: 8px 10px; } .draco-missions .m-entete { display: flex; justify-content: space-between; gap: 8px; align-items: baseline; } -.draco-missions .m-statut { font-size: 11.5px; font-weight: 700; color: #6c7268; white-space: nowrap; } +.draco-missions .m-statut { font-size: 11.5px; font-weight: 700; color: var(--p-doux); white-space: nowrap; } .draco-missions .m-statut.st-succeeded { color: #2ea36b; } .draco-missions .m-statut.st-failed { color: #cf4b32; } .draco-missions .m-statut.st-running, .draco-missions .m-statut.st-paused_question { color: #9a6a1c; } -.draco-missions .m-meta { font-size: 12px; color: #6c7268; } +.draco-missions .m-meta { font-size: 12px; color: var(--p-doux); } .draco-missions .m-rapport { font-size: 12.5px; margin-top: 5px; white-space: pre-wrap; word-wrap: break-word; } -.draco-missions .m-annuler { margin-top: 6px; border: 0; border-radius: 7px; padding: 4px 9px; font: 600 12px system-ui; cursor: pointer; background: #f6e3de; color: #a03a28; } +.draco-missions .m-annuler { margin-top: 6px; border: 0; border-radius: 7px; padding: 4px 9px; font: 600 12px system-ui; cursor: pointer; background: var(--p-danger-fond); color: var(--p-danger); } +/* ── Rendu Markdown (HTML produit par le service) ──────────── */ +.draco-msg.md, .draco-missions .m-rapport.md { white-space: normal; } +.draco-msg.md > *:first-child, .m-rapport.md > *:first-child { margin-top: 0; } +.draco-msg.md > *:last-child, .m-rapport.md > *:last-child { margin-bottom: 0; } +.draco-msg.md p, .m-rapport.md p { margin: 6px 0; } +.draco-msg.md h1, .draco-msg.md h2, .draco-msg.md h3, +.draco-msg.md h4, .draco-msg.md h5, .draco-msg.md h6 { margin: 10px 0 4px; line-height: 1.3; } +.draco-msg.md h1 { font-size: 16.5px; } .draco-msg.md h2 { font-size: 15.5px; } +.draco-msg.md h3 { font-size: 14.5px; } .draco-msg.md h4, +.draco-msg.md h5, .draco-msg.md h6 { font-size: 13.5px; } +.draco-msg.md ul, .draco-msg.md ol, .m-rapport.md ul, .m-rapport.md ol { margin: 6px 0; padding-left: 20px; } +.draco-msg.md li, .m-rapport.md li { margin: 2px 0; } +.draco-msg.md code, .m-rapport.md code { + background: var(--p-code); border-radius: 5px; padding: 1px 5px; + font: 12.5px ui-monospace, "Cascadia Mono", Consolas, monospace; +} +.draco-msg.md pre, .m-rapport.md pre { + background: var(--p-code); border-radius: 9px; padding: 9px 11px; + overflow-x: auto; margin: 7px 0; +} +.draco-msg.md pre code, .m-rapport.md pre code { background: none; padding: 0; } +.draco-msg.md blockquote, .m-rapport.md blockquote { + border-left: 3px solid var(--p-accent); margin: 7px 0; padding: 2px 0 2px 11px; + color: var(--p-doux); +} +.draco-msg.md blockquote.callout, .m-rapport.md blockquote.callout { + border-radius: 0 8px 8px 0; padding: 6px 11px; color: var(--p-texte); + background: var(--p-chip); +} +.draco-msg.md blockquote.callout-warning { border-left-color: #e8a13c; } +.draco-msg.md blockquote.callout-danger { border-left-color: #cf4b32; } +.draco-msg.md blockquote.callout-tip { border-left-color: #2ea36b; } +.draco-msg.md a, .m-rapport.md a { color: var(--p-lien); } +.draco-msg.md table, .m-rapport.md table { + border-collapse: collapse; margin: 7px 0; font-size: 12.5px; + display: block; overflow-x: auto; max-width: 100%; +} +.draco-msg.md th, .draco-msg.md td, .m-rapport.md th, .m-rapport.md td { + border: 1px solid var(--p-bord); padding: 4px 8px; text-align: left; +} +.draco-msg.md hr, .m-rapport.md hr { border: 0; border-top: 1px solid var(--p-bord); margin: 9px 0; } +.draco-msg.md input[type="checkbox"], .m-rapport.md input[type="checkbox"] { margin-right: 5px; } diff --git a/frontend/draco-panneau.js b/frontend/draco-panneau.js index 1eeeb55..5a0d8ec 100644 --- a/frontend/draco-panneau.js +++ b/frontend/draco-panneau.js @@ -1,43 +1,129 @@ -/* Panneau Spark — branchement au service d'agents (Fusion, J1 → J5). +/* Panneau Spark — branchement au service d'agents (Fusion, J1 → Panneau v2). * * Parle à l'API du service d'agents (contrat de dracodev-commons) : * GET /api/v1/me — identité (cookie draco_session) * POST /api/v1/chat — conversation réelle du noyau (J2) : - * LLM DeepSeek + outils MCP des apps - * GET /api/v1/conversations/… — historique de la conversation - * GET /api/v1/executors — registre (noyau, sous-agents J3, + * LLM DeepSeek + outils MCP des apps ; + * la réponse arrive avec son HTML + * Markdown rendu côté service (v2) + * GET /api/v1/conversations — discussions façon Muse (v2) : une + * principale perpétuelle + des + * parallèles créées/archivées/ + * supprimées par l'utilisateur + * GET /api/v1/conversations/… — historique d'une discussion (les + * messages agent portent leur html) + * GET /api/v1/executors — registre (noyau, sous-agents J3, * externes J4 : état de configuration) - * POST /api/v1/missions — missions longues (J5) : lancement, - * suivi, rapport, annulation + * POST /api/v1/missions — missions longues (J5) + * Panneau v2 (Lot 1) : rendu Markdown, largeur réglable à la souris + * (persistée), thème clair/sombre aligné sur l'app hôte + * (html[data-theme], repli prefers-color-scheme, suivi en direct). * États honnêtes : service injoignable / session non reconnue / LLM non * configuré / exécuteur non configuré sont affichés tels quels. */ (function () { "use strict"; var API = "https://agent.dracodev.net"; var convId = null; - try { convId = sessionStorage.getItem("draco_panneau_conv") || null; } catch (e) { /* stockage indispo */ } + var convKind = null; // 'principale' | 'parallele' + var convTitre = ""; var etatConnu = false; - var historiqueCharge = false; var root = null, msgsEl = null, etatEl = null, inputEl = null, sendBtn = null; + var titreEl = null, tiroirEl = null; function domaine() { try { return localStorage.getItem("draco_domain") || "pro"; } catch (e) { return "pro"; } } + function stockerConv() { + try { + if (convId) sessionStorage.setItem("draco_panneau_conv", convId); + else sessionStorage.removeItem("draco_panneau_conv"); + } catch (e) { /* stockage indisponible */ } + } + function convStockee() { + try { return sessionStorage.getItem("draco_panneau_conv") || null; } + catch (e) { return null; } + } + + /* ── Thème : suivre l'app hôte ─────────────────────────────── */ + function themeHote() { + var t = document.documentElement.getAttribute("data-theme"); + if (t === "dark" || t === "light") return t; + if (document.documentElement.classList.contains("dark") || + document.body.classList.contains("dark")) return "dark"; + try { + if (window.matchMedia("(prefers-color-scheme: dark)").matches) return "dark"; + } catch (e) { /* pas de matchMedia */ } + return "light"; + } + function appliquerTheme() { + if (root) root.setAttribute("data-draco-theme", themeHote()); + } + function surveillerTheme() { + try { + new MutationObserver(appliquerTheme).observe(document.documentElement, + { attributes: true, attributeFilter: ["data-theme", "class"] }); + window.matchMedia("(prefers-color-scheme: dark)") + .addEventListener("change", appliquerTheme); + } catch (e) { /* surveillance facultative */ } + } + + /* ── Largeur réglable ──────────────────────────────────────── */ + function largeurStockee() { + try { + var v = parseInt(localStorage.getItem("draco_panneau_largeur") || "", 10); + return isNaN(v) ? null : v; + } catch (e) { return null; } + } + function appliquerLargeur() { + if (!root) return; + var v = largeurStockee(); + root.style.width = v ? Math.min(v, Math.round(window.innerWidth * 0.96)) + "px" : ""; + } + function brancherPoignee(poignee) { + poignee.addEventListener("pointerdown", function (ev) { + if (window.innerWidth <= 700) return; // mobile : pleine largeur + ev.preventDefault(); + var x0 = ev.clientX, w0 = root.getBoundingClientRect().width; + function bouger(e2) { + var w = Math.max(300, Math.min(760, w0 + (x0 - e2.clientX))); + root.style.width = w + "px"; + } + function lacher(e2) { + document.removeEventListener("pointermove", bouger); + document.removeEventListener("pointerup", lacher); + var w = Math.round(root.getBoundingClientRect().width); + try { localStorage.setItem("draco_panneau_largeur", String(w)); } catch (e) { /* ok */ } + } + document.addEventListener("pointermove", bouger); + document.addEventListener("pointerup", lacher); + }); + poignee.addEventListener("dblclick", function () { + try { localStorage.removeItem("draco_panneau_largeur"); } catch (e) { /* ok */ } + appliquerLargeur(); + }); + } function construire() { root = document.createElement("aside"); root.className = "draco-panneau"; root.setAttribute("aria-label", "Spark, l'agent commun"); root.innerHTML = + '
' + '