diff --git a/.github/workflows/desktop-release.yml b/.github/workflows/desktop-release.yml
index 06e8c86..465b0f5 100644
--- a/.github/workflows/desktop-release.yml
+++ b/.github/workflows/desktop-release.yml
@@ -70,6 +70,13 @@ jobs:
shell: pwsh
run: choco install wixtoolset -y --no-progress
+ # Tesseract OCR : non preinstalle sur windows-latest. Requis pour que
+ # build-windows.ps1 embarque l'OCR des PDF scannes (sinon il skip en
+ # degradation gracieuse). Installe dans %ProgramFiles%\Tesseract-OCR.
+ - name: Install Tesseract OCR
+ shell: pwsh
+ run: choco install tesseract -y --no-progress
+
# Version de l'installeur = version du tag (push) OU de l'input (manuel).
# Sorties : version (numerique X.Y.Z pour le MSI), tag (vX.Y.Z[-beta]),
# isbeta (true/false) — independant du nom de ref (qui est une branche en manuel).
diff --git a/brain/app/main.py b/brain/app/main.py
index 0a7182d..dd79092 100644
--- a/brain/app/main.py
+++ b/brain/app/main.py
@@ -26,7 +26,7 @@ from app.infrastructure.ollama_model_installer import ensure_ollama_embedding_mo
app = FastAPI(
title="LoreMind Brain",
description="Backend IA pour la génération de contenu narratif.",
- version="0.16.0",
+ version="0.16.1",
)
logger = logging.getLogger(__name__)
diff --git a/brain/run_local.py b/brain/run_local.py
index 3cfa2cd..c0fa422 100644
--- a/brain/run_local.py
+++ b/brain/run_local.py
@@ -16,7 +16,21 @@ ailleurs, sous ~/.loremind/brain, pour y ecrire le dossier data/).
import os
import sys
-sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
+_HERE = os.path.dirname(os.path.abspath(__file__))
+sys.path.insert(0, _HERE)
+
+# OCR : si un Tesseract est bundlé à côté (mode desktop), on y pointe pytesseract
+# AVANT que l'app n'importe le pdf_extractor (qui détecte la version au chargement).
+# tessdata (fra+eng) est embarqué dans tesseract/tessdata. Sans ce bloc, l'OCR
+# reste désactivé en dégradation gracieuse (PDF born-digital OK, scans signalés).
+_TESS = os.path.join(_HERE, "tesseract", "tesseract.exe")
+if os.path.exists(_TESS):
+ os.environ.setdefault("TESSDATA_PREFIX", os.path.join(_HERE, "tesseract"))
+ try:
+ import pytesseract
+ pytesseract.pytesseract.tesseract_cmd = _TESS
+ except ImportError:
+ pass
import uvicorn # noqa: E402
diff --git a/core/pom.xml b/core/pom.xml
index d043c12..6ba2875 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -14,7 +14,7 @@
com.loremind
loremind-core
- 0.16.0
+ 0.16.1
LoreMind Core
Backend Core - Architecture Hexagonale
diff --git a/installers/desktop/build-windows.ps1 b/installers/desktop/build-windows.ps1
index 7429eba..f27daef 100644
--- a/installers/desktop/build-windows.ps1
+++ b/installers/desktop/build-windows.ps1
@@ -137,6 +137,27 @@ if (-not $SkipBrain) {
Copy-Item (Join-Path $BrainDir 'app') (Join-Path $BrainEmbed 'app') -Recurse
Copy-Item (Join-Path $BrainDir 'run_local.py') (Join-Path $BrainEmbed 'run_local.py')
+ # e) Tesseract (OCR des PDF scannes). Pas de zip portable officiel : on COPIE
+ # l'install UB-Mannheim (tesseract.exe + DLL), prerequis a installer une
+ # fois via `choco install tesseract`. Langues fra+eng tirees de tessdata_fast
+ # (leger, coherent). Si Tesseract n'est pas installe -> skip gracieux :
+ # l'app reste fonctionnelle, seul l'OCR des scans manquera (cf. run_local.py
+ # + pdf_extractor.py qui detectent l'absence et degradent proprement).
+ $tessSrc = Join-Path $env:ProgramFiles 'Tesseract-OCR'
+ if (Test-Path (Join-Path $tessSrc 'tesseract.exe')) {
+ $tessDst = Join-Path $BrainEmbed 'tesseract'
+ Copy-Item $tessSrc $tessDst -Recurse
+ New-Item -ItemType Directory -Force -Path (Join-Path $tessDst 'tessdata') | Out-Null
+ foreach ($lang in @('fra','eng')) {
+ Invoke-WebRequest -UseBasicParsing `
+ -Uri "https://github.com/tesseract-ocr/tessdata_fast/raw/main/$lang.traineddata" `
+ -OutFile (Join-Path $tessDst "tessdata\$lang.traineddata")
+ }
+ Write-Ok "Tesseract bundle (OCR des scans actif)"
+ } else {
+ Write-Host " !! Tesseract introuvable ($tessSrc) -> OCR des scans NON bundle (degradation gracieuse). Pour l'activer : choco install tesseract" -ForegroundColor Yellow
+ }
+
Write-Ok "Brain prepare (brain/dist-embed : python embeddable + deps + sources)"
} else { Write-Step "Brain : saute (--SkipBrain)" }
@@ -183,6 +204,13 @@ New-Item -ItemType Directory -Force -Path $OutDir | Out-Null
# ne contient de virgule) sont bindes en List par Spring.
$brainCmd = '$APPDIR\brain\python\python.exe,$APPDIR\brain\run_local.py'
+# --win-upgrade-uuid : UUID STABLE du produit. Permet a Windows Installer de
+# reconnaitre qu'une nouvelle version est une MISE A JOUR du meme produit -> upgrade
+# en place propre (pas besoin de desinstaller avant, pas de doublon). Les donnees
+# (base H2, images) vivent de toute facon dans ~/.loremind, HORS du dossier
+# d'installation, donc jamais touchees par l'installeur.
+# /!\ NE JAMAIS CHANGER cet UUID : le modifier casserait la chaine d'upgrade.
+#
# Note : pas de --win-console (app de bureau). Les logs Spring/Brain peuvent
# etre rediriges vers un fichier via une option ulterieure si besoin de debug.
jpackage `
@@ -197,6 +225,7 @@ jpackage `
--java-options '-Dspring.profiles.active=local' `
--java-options "-Dbrain.sidecar.command=$brainCmd" `
--win-per-user-install `
+ --win-upgrade-uuid 'a7c4e1d2-9b3f-4e6a-8d05-1f2c3b4a5e6d' `
--win-menu --win-menu-group 'LoreMind' `
--win-shortcut --win-dir-chooser
diff --git a/web/nginx.conf b/web/nginx.conf
index f4e48b3..31bef96 100644
--- a/web/nginx.conf
+++ b/web/nginx.conf
@@ -34,6 +34,18 @@ server {
try_files $uri =404;
}
+ # Fichiers de traduction (assets/i18n/*.json) : nom STABLE (non hashe),
+ # donc JAMAIS caches — sinon le navigateur ressert un vieux fr.json apres une
+ # mise a jour et affiche des cles brutes (ex : settings.data.* en clair).
+ # Aligne sur le mode desktop (LocalWebConfig sert deja l'i18n en no-cache).
+ # ^~ : ce prefixe l'emporte sur la regex d'assets ci-dessous.
+ location ^~ /assets/i18n/ {
+ add_header Cache-Control "no-cache, no-store, must-revalidate" always;
+ add_header Pragma "no-cache" always;
+ expires 0;
+ try_files $uri =404;
+ }
+
# Assets Angular avec hash dans le nom (main..js, etc.) :
# immuables, peuvent etre caches longtemps.
location ~* \.(?:js|css|woff2?|ttf|svg|png|jpg|jpeg|webp|ico)$ {
diff --git a/web/package-lock.json b/web/package-lock.json
index a0a76db..a250aaf 100644
--- a/web/package-lock.json
+++ b/web/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "loremind-web",
- "version": "0.16.0",
+ "version": "0.16.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "loremind-web",
- "version": "0.16.0",
+ "version": "0.16.1",
"dependencies": {
"@angular/animations": "^21.2.16",
"@angular/common": "^21.2.16",
diff --git a/web/package.json b/web/package.json
index 3ba5f46..4a548dd 100644
--- a/web/package.json
+++ b/web/package.json
@@ -1,6 +1,6 @@
{
"name": "loremind-web",
- "version": "0.16.0",
+ "version": "0.16.1",
"description": "LoreMind Frontend - Angular",
"scripts": {
"ng": "ng",