diff --git a/kazeia-android/app/build.gradle.kts b/kazeia-android/app/build.gradle.kts index 15fbe9a..09de200 100644 --- a/kazeia-android/app/build.gradle.kts +++ b/kazeia-android/app/build.gradle.kts @@ -44,8 +44,8 @@ android { applicationId = "com.kazeia" minSdk = 28 targetSdk = 36 - versionCode = 2 - versionName = "0.1.1" + versionCode = 4 + versionName = "0.1.3" // WebDAV de distribution — injecté depuis local.properties. buildConfigField("String", "WEBDAV_BASE", "\"${localProp("webdav.base")}\"") diff --git a/kazeia-android/app/src/main/java/com/kazeia/KazeiaPaths.kt b/kazeia-android/app/src/main/java/com/kazeia/KazeiaPaths.kt index b0bc744..f11eb9c 100644 --- a/kazeia-android/app/src/main/java/com/kazeia/KazeiaPaths.kt +++ b/kazeia-android/app/src/main/java/com/kazeia/KazeiaPaths.kt @@ -26,6 +26,7 @@ object KazeiaPaths { private const val LEGACY_MODELS = "/data/local/tmp/kazeia/models" private const val LEGACY_LLM = "/data/local/tmp/kazeia-et" + private const val LEGACY_RAG = "/data/local/tmp/kazeia/rag_corpus" /** Racine modèles STT/TTS (Whisper, GGUF, qwen3-tts-npu ; voix via `/../`). */ @Volatile var modelsDir: String = LEGACY_MODELS @@ -35,6 +36,13 @@ object KazeiaPaths { @Volatile var llmDir: String = LEGACY_LLM private set + /** Corpus RAG. Priorité INVERSE des modèles : l'EXTERNE prime dès qu'il est + * non vide, car c'est là que l'installeur/OTA dépose le composant + * `rag_corpus` — sur une tablette dev, les modèles restent legacy mais le + * corpus à jour arrive par le catalogue. Fallback legacy (adb push) sinon. */ + @Volatile var ragCorpusDir: String = LEGACY_RAG + private set + @Volatile private var initialized = false /** @@ -50,8 +58,9 @@ object KazeiaPaths { val root = File(context.getExternalFilesDir(null), "kazeia") modelsDir = resolve(File(root, "models"), File(LEGACY_MODELS)) llmDir = resolve(File(root, "llm"), File(LEGACY_LLM)) + ragCorpusDir = resolveExternalFirst(File(root, "rag_corpus"), File(LEGACY_RAG)) initialized = true - Log.i(TAG, "modelsDir=$modelsDir | llmDir=$llmDir") + Log.i(TAG, "modelsDir=$modelsDir | llmDir=$llmDir | ragCorpusDir=$ragCorpusDir") } } @@ -61,4 +70,11 @@ object KazeiaPaths { legacy.absolutePath else external.absolutePath + + /** Externe si non vide (déposé par l'installeur/OTA), sinon legacy (adb push). */ + private fun resolveExternalFirst(external: File, legacy: File): String = + if (external.isDirectory && !external.list().isNullOrEmpty()) + external.absolutePath + else + legacy.absolutePath } diff --git a/kazeia-android/app/src/main/java/com/kazeia/config/ConfigStore.kt b/kazeia-android/app/src/main/java/com/kazeia/config/ConfigStore.kt index 8b978a7..e72c60a 100644 --- a/kazeia-android/app/src/main/java/com/kazeia/config/ConfigStore.kt +++ b/kazeia-android/app/src/main/java/com/kazeia/config/ConfigStore.kt @@ -44,10 +44,13 @@ class ConfigStore private constructor(private val file: File) { * EngineLlmAdapter (libkazeia_engine + GGUF Qwen3.5). Defaults safe = "prod". * Bascule "lib" nécessite libllama.so fork ql dans jniLibs. */ val llmEngine: String = "prod", - /** Backend TTS : "prod" = Qwen3TtsEngine legacy, "lib" = libkazeia_tts unifié. - * Defaults safe = "prod". Bascule "lib" nécessite libllama.so fork ql + retrait - * des classes legacy `tts_talker_cpu`/`tts_cp_cpu` (incompat ABI struct). */ - val ttsEngine: String = "prod", + /** Backend TTS : "lib" = libkazeia_tts unifié (SEUL compatible avec le + * libllama.so fork ql embarqué depuis 2026-06-02), "prod" = Qwen3TtsEngine + * legacy — CRASHE (SIGSEGV nativeInit, dérive ABI llama_context_params) tant + * que les .so legacy ne sont pas recompilés contre les headers fork ql. + * Default "lib" depuis 2026-06-11 : l'ancien défaut "prod" mettait toute + * install fraîche en crash-loop au démarrage du service. */ + val ttsEngine: String = "lib", /** RAG (récupération de contexte injecté au prompt). Default OFF : tant que * kazeia-engine n'expose pas embedText + qu'aucun corpus n'est ingéré, * l'activer est inerte (l'embedder n'est pas prêt). Pilotable via admin. */ @@ -113,7 +116,7 @@ class ConfigStore private constructor(private val file: File) { ttsEnabled = true, sttEngine = "prod", llmEngine = "prod", - ttsEngine = "prod" + ttsEngine = "lib" // legacy "prod" = SIGSEGV avec le libllama fork ql embarqué ) } diff --git a/kazeia-android/app/src/main/java/com/kazeia/service/KazeiaService.kt b/kazeia-android/app/src/main/java/com/kazeia/service/KazeiaService.kt index 74ac00a..8b1e8f7 100644 --- a/kazeia-android/app/src/main/java/com/kazeia/service/KazeiaService.kt +++ b/kazeia-android/app/src/main/java/com/kazeia/service/KazeiaService.kt @@ -668,7 +668,7 @@ Pas d'introduction, pas d'explication. Juste les 4 lignes en francais. /no_think intent?.getStringExtra("rag_ingest")?.let { dirArg -> // (Ré)ingestion du corpus dans l'instance RAG live : clear + ingestDir. // dirArg vide -> dossier corpus par défaut. Brique de l'app admin future. - val dir = dirArg.ifBlank { "${KazeiaApplication.MODELS_DIR}/../rag_corpus" } + val dir = dirArg.ifBlank { com.kazeia.KazeiaPaths.ragCorpusDir } log("RAG ingest: $dir") serviceScope.launch { val r = rag @@ -2081,7 +2081,7 @@ Pas d'introduction, pas d'explication. Juste les 4 lignes en francais. /no_think // que le delta) : couvre le 1er démarrage ET les MAJ OTA du composant // rag_corpus (nouveaux fichiers ingérés au redémarrage suivant). if (it.isReady) - it.syncDir("${KazeiaApplication.MODELS_DIR}/../rag_corpus") + it.syncDir(com.kazeia.KazeiaPaths.ragCorpusDir) it.reingestMissing() // embed les docs admin ajoutés hors-ligne rag = it com.kazeia.rag.RagHolder.instance = it