diff --git a/CHANGELOG.md b/CHANGELOG.md index add8e06..9ddccd4 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.73.1**. +> [Unreleased](#unreleased). La dernière version livrée est **2.74.0**. --- @@ -14,6 +14,21 @@ et [Semantic Versioning](https://semver.org/spec/v2.0.0.html). --- +## [2.74.0] — 2026-10-22 + +### Ajouté + +- **Panneau Spark intégré (#218, Fusion)** — le bouton Spark de la + barre commune ouvre le panneau de l'agent commun (conversation, + Aujourd'hui, approbations, missions longues), comme dans TikTak, + Flowdeck et Kanbante : assets partagés `frontend/draco-panneau.js` + et `frontend/draco-panneau.css` vendangés à l'identique, action + `spark` branchée sur `DRACO_PANNEAU.toggle()`. La CSP nomme + `https://agent.dracodev.net` en `connect-src` (seul hôte ajouté). + Redéploiement Docker requis. + +--- + ## [2.73.1] — 2026-10-21 ### Corrigé diff --git a/README.fr.md b/README.fr.md index f4feac9..92d975a 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.73.1). +Consultez le [CHANGELOG.md](./CHANGELOG.md) pour l'historique complet de toutes les versions (v1.0.0 → v2.74.0). --- -*Projet : ObsiGate | Version : 2.73.1 | Dernière mise à jour : Septembre 2026* +*Projet : ObsiGate | Version : 2.74.0 | Dernière mise à jour : Septembre 2026* diff --git a/README.md b/README.md index 9225c0a..58fe4e2 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.73.1). +See [CHANGELOG.md](./CHANGELOG.md) for the complete version history (v1.0.0 → v2.74.0). --- -*Project: ObsiGate | Version: 2.73.1 | Last updated: September 2026* +*Project: ObsiGate | Version: 2.74.0 | Last updated: September 2026* diff --git a/VERSION b/VERSION index 50239e0..04b6fa2 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.73.1 +2.74.0 diff --git a/backend/main.py b/backend/main.py index 782329a..b434fa2 100644 --- a/backend/main.py +++ b/backend/main.py @@ -191,7 +191,7 @@ class SecurityHeadersMiddleware(BaseHTTPMiddleware): f"script-src 'self' 'nonce-{nonce}' blob: https://cdnjs.cloudflare.com https://unpkg.com https://esm.sh https://cdn.jsdelivr.net https://static.cloudflareinsights.com; " "style-src 'self' 'unsafe-inline' https://cdnjs.cloudflare.com https://fonts.googleapis.com https://cdn.jsdelivr.net https://esm.sh; " "img-src 'self' data: blob:; " - "connect-src 'self' blob: https://esm.sh https://unpkg.com https://cdnjs.cloudflare.com https://fonts.googleapis.com https://fonts.gstatic.com https://cdn.jsdelivr.net; " + "connect-src 'self' blob: https://esm.sh https://unpkg.com https://cdnjs.cloudflare.com https://fonts.googleapis.com https://fonts.gstatic.com https://cdn.jsdelivr.net https://agent.dracodev.net; " "font-src 'self' data: https://fonts.gstatic.com https://esm.sh; " "worker-src 'self' blob:; " "frame-src 'self' blob:; " diff --git a/desktop/Cargo.lock b/desktop/Cargo.lock index 1fd4e8e..aac3a23 100644 --- a/desktop/Cargo.lock +++ b/desktop/Cargo.lock @@ -2626,7 +2626,7 @@ dependencies = [ [[package]] name = "obsigate-desktop" -version = "2.73.1" +version = "2.74.0" dependencies = [ "chrono", "env_logger", diff --git a/desktop/Cargo.toml b/desktop/Cargo.toml index 1c56dc9..5a521e2 100644 --- a/desktop/Cargo.toml +++ b/desktop/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "obsigate-desktop" -version = "2.73.1" +version = "2.74.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 899d8da..228ec59 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.73.1", + "version": "2.74.0", "identifier": "com.obsigate.desktop", "build": { "frontendDist": "../frontend", diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index 9e1fc2d..320d86e 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -1,6 +1,6 @@ # ObsiGate — Roadmap -> **Version :** 2.73.1 | **Dernière mise à jour :** 2026-10-21 +> **Version :** 2.74.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)** @@ -30,6 +30,24 @@ ## 🔵 En cours +### 218. Fusion — panneau Spark intégré (agent commun) + +- **Effort :** ~0,5 jour | **Impact :** 🟢 | **Ouvert :** 2026-10-21 | **Statut :** 🔵 en cours +- **Fiche :** [features/fusion-panneau-spark-218.md](./features/fusion-panneau-spark-218.md) +- **Description :** le bouton Spark de la barre commune (#215) ouvre le + panneau de l'agent commun (service d'agents dracodev : conversation, + Aujourd'hui, approbations, missions longues), comme dans TikTak, + Flowdeck et Kanbante. Assets partagés vendangés à l'identique ; + la CSP nomme le service en `connect-src`. +- **Sous-tâches :** + - [x] Assets `frontend/draco-panneau.js` / `frontend/draco-panneau.css` + vendangés depuis le panneau partagé du programme + - [x] `frontend/index.html` : link CSS + script, action `spark` → + `DRACO_PANNEAU.toggle()` (repli honnête si le panneau ne charge pas) + - [x] CSP `connect-src` : `https://agent.dracodev.net` ajouté + (`backend/main.py`, seul hôte ajouté) + - [x] Tests `test_draco_barre.py` (intégration + CSP verrouillées) + ### 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-218.md b/docs/features/fusion-panneau-spark-218.md new file mode 100644 index 0000000..3ca6713 --- /dev/null +++ b/docs/features/fusion-panneau-spark-218.md @@ -0,0 +1,38 @@ +# #218 — Fusion : panneau Spark intégré (agent commun) + +**Contexte.** Le programme Fusion a livré le service d'agents commun +(agent-commun : conversation LLM, lectures/écritures des quatre +applications via approbations, sous-agents, missions longues). Trois +applications affichaient déjà son panneau partagé (TikTak, Flowdeck, +Kanbante) ; ObsiGate, pourtant émettrice de l'identité `draco_session`, +gardait le message d'attente « arrive en phase 4 » sur le bouton Spark +de sa barre commune (#215). + +**Livraison.** + +- Assets vendangés à l'identique des autres applications : + `frontend/draco-panneau.js` et `frontend/draco-panneau.css`, à la + racine de `frontend/` comme les autres assets draco (servis par le + montage `/static`, `Cache-Control: no-cache` déjà en place — aucun + mécanisme de versionnage à ajouter, `index.html` n'est pas un + gabarit Jinja). +- `frontend/index.html` : lien CSS après celui de la barre, script + différé après `draco-liens.js`, action `spark` de + `DRACO_BAR_CONFIG.onAction` branchée sur + `window.DRACO_PANNEAU.toggle()` avec repli explicite si l'asset ne + charge pas. +- CSP (`backend/main.py`, `SecurityHeadersMiddleware`) : + `https://agent.dracodev.net` ajouté à `connect-src` — le panneau + appelle le service en `fetch` avec le cookie de session ; aucun + autre hôte n'est ouvert (précédent : Flowdeck, même exception). + +**Vérifications.** Tests `tests/test_draco_barre.py` étendus +(présence et références des assets, branche spark, hôte CSP) ; +vérification visuelle et E2E à confirmer après redéploiement Docker +(le panneau, `z-index: 400`, cohabite avec des surfaces ObsiGate à +z-index plus élevé — à observer en réel). + +**Hors périmètre.** Les textes du panneau vivent dans l'asset partagé +du programme (français, identique dans les quatre applications) ; ils +ne passent pas par les locales FR/EN d'ObsiGate — écart assumé au +niveau du programme, pas de cette fiche. diff --git a/frontend/draco-panneau.css b/frontend/draco-panneau.css new file mode 100644 index 0000000..743bc07 --- /dev/null +++ b/frontend/draco-panneau.css @@ -0,0 +1,83 @@ +/* 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. */ +.draco-panneau { + position: fixed; top: 0; right: 0; height: 100dvh; width: 388px; max-width: 94vw; + background: #fbfbfa; color: #242624; 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.open { transform: translateX(0); } +.draco-panneau-hd { + display: flex; align-items: center; gap: 9px; + padding: 13px 15px; border-bottom: 1px solid #e4e5e0; background: #fff; +} +.draco-panneau-hd .titre { font-weight: 700; font-size: 15px; } +.draco-panneau-hd .soustitre { font-size: 12px; color: #6c7268; } +.draco-panneau-hd .fermer { + margin-left: auto; border: 0; background: #eef0ea; 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; +} +.draco-panneau-outils button:hover { background: #e9ebe4; } +.draco-appro { + align-self: stretch; background: #fdf6ec; 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-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.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 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-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-panneau-form { display: flex; gap: 8px; } +.draco-panneau-form input { + flex: 1; border: 1px solid #d6d8d1; border-radius: 10px; padding: 9px 11px; font: inherit; +} +.draco-panneau-form button { + border: 0; border-radius: 10px; background: #7c5cd6; 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-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; +} +.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 .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 .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.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-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; } diff --git a/frontend/draco-panneau.js b/frontend/draco-panneau.js new file mode 100644 index 0000000..1eeeb55 --- /dev/null +++ b/frontend/draco-panneau.js @@ -0,0 +1,380 @@ +/* Panneau Spark — branchement au service d'agents (Fusion, J1 → J5). + * + * 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, + * externes J4 : état de configuration) + * POST /api/v1/missions — missions longues (J5) : lancement, + * suivi, rapport, annulation + * É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 etatConnu = false; + var historiqueCharge = false; + var root = null, msgsEl = null, etatEl = null, inputEl = null, sendBtn = null; + + function domaine() { + try { return localStorage.getItem("draco_domain") || "pro"; } catch (e) { return "pro"; } + } + + function construire() { + root = document.createElement("aside"); + root.className = "draco-panneau"; + root.setAttribute("aria-label", "Spark, l'agent commun"); + root.innerHTML = + '