Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e2153435dc | ||
|
|
f307ecb380 | ||
|
|
50b823e76d | ||
|
|
84bda90065 |
+1
-1
@@ -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).
|
et [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
> **En cours de développement** : les changements non publiés sont dans la section
|
> **En cours de développement** : les changements non publiés sont dans la section
|
||||||
> [Unreleased](#unreleased). La dernière version publiée est **2.1.0**.
|
> [Unreleased](#unreleased). La dernière version publiée est **2.2.1**.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -35,7 +35,7 @@ COPY frontend/ ./frontend/
|
|||||||
# exclu du .dockerignore pour que le build utilise TOUJOURS l'ARG ci-dessous
|
# exclu du .dockerignore pour que le build utilise TOUJOURS l'ARG ci-dessous
|
||||||
# (jamais un fichier stale "1.8.0-...-dirty" du contexte build qui afficherait
|
# (jamais un fichier stale "1.8.0-...-dirty" du contexte build qui afficherait
|
||||||
# une vieille version au lieu du tag courant).
|
# une vieille version au lieu du tag courant).
|
||||||
ARG VERSION=2.1.0
|
ARG VERSION=2.2.1
|
||||||
RUN test -f backend/VERSION || echo "$VERSION" > backend/VERSION
|
RUN test -f backend/VERSION || echo "$VERSION" > backend/VERSION
|
||||||
|
|
||||||
# Create non-root user for security + data directory for auth persistence
|
# Create non-root user for security + data directory for auth persistence
|
||||||
|
|||||||
@@ -106,6 +106,14 @@ Ce vault est utilisé pour les tests de développement d'ObsiGate.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# ----- Resolve version from git before Docker build -----
|
||||||
|
$Version = (git describe --tags --dirty 2>$null) -replace '^v',''
|
||||||
|
if (-not $Version) { $Version = "0.0.0" }
|
||||||
|
$Version | Out-File -Encoding ascii -NoNewline -FilePath "backend\VERSION"
|
||||||
|
# Export so docker compose substitutes ${VERSION} in the build arg
|
||||||
|
$env:VERSION = $Version
|
||||||
|
Write-Info "Version : $Version"
|
||||||
|
|
||||||
# ----- Build the image -----
|
# ----- Build the image -----
|
||||||
$BuildArgs = @("-f", $ComposeFile)
|
$BuildArgs = @("-f", $ComposeFile)
|
||||||
if (-not $UseCache) {
|
if (-not $UseCache) {
|
||||||
|
|||||||
@@ -196,6 +196,8 @@ fi
|
|||||||
# Generate VERSION file from git before Docker build
|
# Generate VERSION file from git before Docker build
|
||||||
VERSION=$(git describe --tags --dirty 2>/dev/null | sed 's/^v//' || echo "0.0.0-dev")
|
VERSION=$(git describe --tags --dirty 2>/dev/null | sed 's/^v//' || echo "0.0.0-dev")
|
||||||
echo "$VERSION" > backend/VERSION
|
echo "$VERSION" > backend/VERSION
|
||||||
|
# Export so docker compose substitutes ${VERSION} in the build arg
|
||||||
|
export VERSION
|
||||||
info "Version: $VERSION"
|
info "Version: $VERSION"
|
||||||
|
|
||||||
$COMPOSE_CMD -f "$COMPOSE_FILE" build "${BUILD_FLAGS[@]}" "${BUILD_ARGS[@]}"
|
$COMPOSE_CMD -f "$COMPOSE_FILE" build "${BUILD_FLAGS[@]}" "${BUILD_ARGS[@]}"
|
||||||
|
|||||||
+2
-2
@@ -14,9 +14,9 @@ services:
|
|||||||
args:
|
args:
|
||||||
# VERSION est injecte par build.sh/CI via `git describe`.
|
# VERSION est injecte par build.sh/CI via `git describe`.
|
||||||
# En `docker compose build` direct (sans build.sh), on retombe sur le
|
# En `docker compose build` direct (sans build.sh), on retombe sur le
|
||||||
# DERNIER TAG (v2.1.0) et non 0.0.0-dev, pour ne jamais afficher "0.0.0"
|
# DERNIER TAG (v2.2.1) et non 0.0.0-dev, pour ne jamais afficher "0.0.0"
|
||||||
# dans le header / la boîte À propos. Packagé par backend/VERSION.
|
# dans le header / la boîte À propos. Packagé par backend/VERSION.
|
||||||
VERSION: ${VERSION:-2.1.0}
|
VERSION: ${VERSION:-2.2.1}
|
||||||
image: obsigate:latest
|
image: obsigate:latest
|
||||||
container_name: obsigate
|
container_name: obsigate
|
||||||
user: "1000:1000"
|
user: "1000:1000"
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
# ObsiGate — Roadmap
|
# ObsiGate — Roadmap
|
||||||
|
|
||||||
> **Version :** 2.1.0-dev | **Dernière mise à jour :** 2026-09-10
|
> **Version :** 2.2.1-dev | **Dernière mise à jour :** 2026-09-10
|
||||||
> Revue de cohérence roadmap ↔ code : cases cochées selon l'état réel vérifié dans le dépôt (#78 docs H1-H3, #67 push, #68 health, #74/#61 optionnels non retenus).
|
> Revue de cohérence roadmap ↔ code : cases cochées selon l'état réel vérifié dans le dépôt (#78 docs H1-H3, #67 push, #68 health, #74/#61 optionnels non retenus).
|
||||||
> Voir aussi [CHANGELOG.md](./CHANGELOG.md), [AUDIT_TECHNIQUE.md](./docs/AUDIT_TECHNIQUE_2026-05-27.md)
|
> Voir aussi [CHANGELOG.md](./CHANGELOG.md), [AUDIT_TECHNIQUE.md](./docs/AUDIT_TECHNIQUE_2026-05-27.md)
|
||||||
|
|
||||||
|
|||||||
@@ -5041,6 +5041,14 @@ curl -X POST https://votre-serveur.com/webhook \
|
|||||||
<i data-lucide="search" style="width: 20px; height: 20px"></i>
|
<i data-lucide="search" style="width: 20px; height: 20px"></i>
|
||||||
<span class="mt-label" data-i18n="settings.search">Recherche</span>
|
<span class="mt-label" data-i18n="settings.search">Recherche</span>
|
||||||
</button>
|
</button>
|
||||||
|
<button
|
||||||
|
class="mt-btn mt-btn-ai"
|
||||||
|
id="mt-ai"
|
||||||
|
title="Assistant AI"
|
||||||
|
aria-label="Ouvrir l'assistant AI"
|
||||||
|
>
|
||||||
|
<i data-lucide="bot" style="width: 24px; height: 24px"></i>
|
||||||
|
</button>
|
||||||
<button
|
<button
|
||||||
class="mt-btn mt-btn-primary"
|
class="mt-btn mt-btn-primary"
|
||||||
id="mt-palette"
|
id="mt-palette"
|
||||||
|
|||||||
@@ -23,7 +23,10 @@ function syncVisibility() {
|
|||||||
_fab.setAttribute('aria-label', label);
|
_fab.setAttribute('aria-label', label);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function onClick() {
|
// Shared entry point used by the floating FAB and the mobile toolbar button.
|
||||||
|
// Reopens a collapsed panel, otherwise opens (or re-focuses) the assistant
|
||||||
|
// for the current application context.
|
||||||
|
export async function openAssistant() {
|
||||||
const panel = document.querySelector('.bookslm-panel');
|
const panel = document.querySelector('.bookslm-panel');
|
||||||
// Collapsed panel: reveal it instead of reopening.
|
// Collapsed panel: reveal it instead of reopening.
|
||||||
if (panel && panel.classList.contains('open') && panel.classList.contains('hidden')) {
|
if (panel && panel.classList.contains('open') && panel.classList.contains('hidden')) {
|
||||||
@@ -34,6 +37,10 @@ async function onClick() {
|
|||||||
await booksLM.openForCurrentContext();
|
await booksLM.openForCurrentContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function onClick() {
|
||||||
|
await openAssistant();
|
||||||
|
}
|
||||||
|
|
||||||
export function initAIFab() {
|
export function initAIFab() {
|
||||||
if (_fab) return;
|
if (_fab) return;
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
Phases 1-5: fixed bar, vault home, file palette, commands, tab switcher */
|
Phases 1-5: fixed bar, vault home, file palette, commands, tab switcher */
|
||||||
import { state } from './state.js';
|
import { state } from './state.js';
|
||||||
import { TabManager } from './ui.js';
|
import { TabManager } from './ui.js';
|
||||||
|
import { openAssistant } from './ai-fab.js';
|
||||||
|
|
||||||
// ── Open file palette (search files) ──
|
// ── Open file palette (search files) ──
|
||||||
function openFilePalette() {
|
function openFilePalette() {
|
||||||
@@ -109,6 +110,7 @@ function toggleExplorer() {
|
|||||||
export function initMobileToolbar() {
|
export function initMobileToolbar() {
|
||||||
const explorerBtn = document.getElementById('mt-explorer');
|
const explorerBtn = document.getElementById('mt-explorer');
|
||||||
const searchBtn = document.getElementById('mt-search');
|
const searchBtn = document.getElementById('mt-search');
|
||||||
|
const aiBtn = document.getElementById('mt-ai');
|
||||||
const paletteBtn = document.getElementById('mt-palette');
|
const paletteBtn = document.getElementById('mt-palette');
|
||||||
const tabsBtn = document.getElementById('mt-tabs');
|
const tabsBtn = document.getElementById('mt-tabs');
|
||||||
const sheetClose = document.getElementById('mt-sheet-close');
|
const sheetClose = document.getElementById('mt-sheet-close');
|
||||||
@@ -117,6 +119,7 @@ export function initMobileToolbar() {
|
|||||||
|
|
||||||
if (explorerBtn) explorerBtn.addEventListener('click', toggleExplorer);
|
if (explorerBtn) explorerBtn.addEventListener('click', toggleExplorer);
|
||||||
if (searchBtn) searchBtn.addEventListener('click', openFilePalette);
|
if (searchBtn) searchBtn.addEventListener('click', openFilePalette);
|
||||||
|
if (aiBtn) aiBtn.addEventListener('click', () => { openAssistant(); });
|
||||||
if (paletteBtn) paletteBtn.addEventListener('click', openCommandPalette);
|
if (paletteBtn) paletteBtn.addEventListener('click', openCommandPalette);
|
||||||
if (tabsBtn) tabsBtn.addEventListener('click', openTabSwitcher);
|
if (tabsBtn) tabsBtn.addEventListener('click', openTabSwitcher);
|
||||||
if (sheetClose) sheetClose.addEventListener('click', closeTabSwitcher);
|
if (sheetClose) sheetClose.addEventListener('click', closeTabSwitcher);
|
||||||
|
|||||||
+38
-1
@@ -7786,6 +7786,37 @@ body.popup-mode .content-area {
|
|||||||
color: var(--accent);
|
color: var(--accent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Hide the floating AI pastille on mobile — the assistant lives in the
|
||||||
|
centre of the bottom toolbar instead (below). */
|
||||||
|
.ai-fab {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* AI assistant — raised central button, stands out from the 4 other items */
|
||||||
|
.mt-btn-ai {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
width: 56px;
|
||||||
|
height: 56px;
|
||||||
|
min-height: 56px;
|
||||||
|
margin: -18px 2px 0;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: var(--accent);
|
||||||
|
color: #fff;
|
||||||
|
box-shadow: 0 4px 14px rgba(0, 0, 0, 0.35), 0 0 0 4px var(--bg-secondary);
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
.mt-btn-ai:active {
|
||||||
|
background: var(--accent);
|
||||||
|
transform: scale(0.94);
|
||||||
|
}
|
||||||
|
.mt-btn-ai svg {
|
||||||
|
width: 26px;
|
||||||
|
height: 26px;
|
||||||
|
}
|
||||||
|
.mt-btn-ai .mt-label {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
/* Tab count badge */
|
/* Tab count badge */
|
||||||
.mt-badge {
|
.mt-badge {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@@ -9196,7 +9227,13 @@ body.popup-mode .content-area {
|
|||||||
background: var(--surface); color: var(--text-secondary); cursor: pointer; font-size: 13px; text-align: left; }
|
background: var(--surface); color: var(--text-secondary); cursor: pointer; font-size: 13px; text-align: left; }
|
||||||
.bookslm-suggestion:hover { background: var(--surface2); color: var(--text-primary); border-color: var(--accent); }
|
.bookslm-suggestion:hover { background: var(--surface2); color: var(--text-primary); border-color: var(--accent); }
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
.bookslm-panel { width: 100%; }
|
.bookslm-panel {
|
||||||
|
width: 100%;
|
||||||
|
/* Clear the fixed bottom toolbar so the input box and the send button
|
||||||
|
are not hidden behind it. The panel background still fills the area
|
||||||
|
behind the bar. */
|
||||||
|
padding-bottom: calc(64px + env(safe-area-inset-bottom, 0px));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── AI Floating Action Button ───────────────────────── */
|
/* ── AI Floating Action Button ───────────────────────── */
|
||||||
|
|||||||
Reference in New Issue
Block a user