From 0a4c22b3d3b35d68eeb2c31e1abb7e4be8f11503 Mon Sep 17 00:00:00 2001 From: James Rich Date: Fri, 12 Jun 2026 06:43:09 -0500 Subject: [PATCH] fix(di): start AppFunctionStateSync from the Application, not createdAtStart MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The google-flavor AppFunctionsModule registered AppFunctionStateSync with createdAtStart = true. Eager creation needs the androidContext binding and immediately spawns the prefs-observing sync coroutine — so any Koin graph built outside a running app failed with NoDefinitionFoundException for android.content.Context. That broke KoinVerificationTest.verifyTypedBootstrapLoadsModuleGraph (the typed koinApplication() bootstrap instantiates eager singletons), failing the shard-app CI job on this branch. The definition is now a plain @Single (the graph stays lazily constructible) and GoogleMeshUtilApplication.onCreate resolves it once after startKoin has bound androidContext — same production behavior, explicit instead of implicit. It was the repo's only createdAtStart. Co-Authored-By: Claude Fable 5 Signed-off-by: James Rich --- .../org/meshtastic/app/GoogleMeshUtilApplication.kt | 9 +++++++++ .../kotlin/org/meshtastic/app/di/AppFunctionsModule.kt | 6 +++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/androidApp/src/google/kotlin/org/meshtastic/app/GoogleMeshUtilApplication.kt b/androidApp/src/google/kotlin/org/meshtastic/app/GoogleMeshUtilApplication.kt index 9e9970235..b3eaef210 100644 --- a/androidApp/src/google/kotlin/org/meshtastic/app/GoogleMeshUtilApplication.kt +++ b/androidApp/src/google/kotlin/org/meshtastic/app/GoogleMeshUtilApplication.kt @@ -18,6 +18,7 @@ package org.meshtastic.app import androidx.appfunctions.service.AppFunctionConfiguration import org.koin.java.KoinJavaComponent.getKoin +import org.meshtastic.app.ai.appfunctions.AppFunctionStateSync import org.meshtastic.app.ai.appfunctions.MeshtasticAppFunctions /** @@ -30,6 +31,14 @@ class GoogleMeshUtilApplication : MeshUtilApplication(), AppFunctionConfiguration.Provider { + override fun onCreate() { + super.onCreate() + // Start the AppFunctions enabled-state sync. Resolved here (after startKoin has bound + // androidContext) rather than via createdAtStart so that Koin graphs built outside a + // running app — verification tests, previews — stay lazily constructible. + getKoin().get() + } + override val appFunctionConfiguration: AppFunctionConfiguration get() = AppFunctionConfiguration.Builder() diff --git a/androidApp/src/google/kotlin/org/meshtastic/app/di/AppFunctionsModule.kt b/androidApp/src/google/kotlin/org/meshtastic/app/di/AppFunctionsModule.kt index c632f1488..a2a8659ef 100644 --- a/androidApp/src/google/kotlin/org/meshtastic/app/di/AppFunctionsModule.kt +++ b/androidApp/src/google/kotlin/org/meshtastic/app/di/AppFunctionsModule.kt @@ -32,7 +32,11 @@ class AppFunctionsModule { @Single fun meshtasticAppFunctions(provider: AiFunctionProvider): MeshtasticAppFunctions = MeshtasticAppFunctions(provider) - @Single(createdAtStart = true) + // NOT createdAtStart: eager creation needs the androidContext binding and spawns the sync + // coroutine, which breaks (and is wrong for) any Koin graph built outside a running app — + // e.g. KoinVerificationTest's typed-bootstrap check. GoogleMeshUtilApplication starts it + // explicitly at app startup instead. + @Single fun appFunctionStateSync( context: Context, prefs: AppFunctionsPrefs,