From 260ed840c6eb0940e7f9a0faba8e4fdc75c5a403 Mon Sep 17 00:00:00 2001 From: John Trujillo Date: Tue, 11 Aug 2026 09:48:37 -0500 Subject: [PATCH 1/8] refactor(ai): split backends into standalone plugins Extract the Gemini and local-LLM backends out of ai-assistant into their own plugins, each owning its settings behind a registry in ai-core, so a backend can be installed and enabled without dragging the others in. --- .gitmodules | 2 +- README.md | 6 +- ai-assistant/ai-assistant.html | 2 +- .../plugins/aiassistant/AiAssistantPlugin.kt | 180 +--- .../backends/BackendFragmentFactory.kt | 82 ++ .../aiassistant/backends/BackendRegistry.kt | 121 +++ .../fragments/AiSettingsFragment.kt | 892 +++--------------- .../gemini/GeminiCatalogGateway.kt | 154 --- .../aiassistant/security/SecureApiKeyStore.kt | 145 --- .../plugins/aiassistant/util/ByteSize.kt | 25 - .../viewmodel/AiSettingsViewModel.kt | 552 ----------- .../aiassistant/viewmodel/ChatViewModel.kt | 307 +++--- ai-assistant/src/main/res/values/strings.xml | 68 +- .../gemini/GeminiKeyOnboardingTest.kt | 20 - .../aiassistant/gemini/KeyVerificationTest.kt | 171 ---- .../memory/ModelMemoryEstimatorTest.kt | 180 ---- .../aiassistant/memory/ModelMemoryGateTest.kt | 79 -- .../aiassistant/util/GgufFileInspectorTest.kt | 93 -- .../aiassistant/util/GgufHeaderReaderTest.kt | 283 ------ .../plugins/aiassistant/util/GgufWriter.kt | 107 --- .../AiSettingsViewModelMemoryTest.kt | 290 ------ .../AiSettingsViewModelVerifyTest.kt | 125 --- .../viewmodel/UserConfirmationTest.kt | 177 ---- ai-backend-gemini/.gitignore | 3 + ai-backend-gemini/README.md | 60 ++ ai-backend-gemini/ai-backend-gemini.html | 120 +++ ai-backend-gemini/build.gradle.kts | 143 +++ ai-backend-gemini/gradle.properties | 10 + ai-backend-gemini/proguard-rules.pro | 16 + ai-backend-gemini/settings.gradle.kts | 35 + .../src/main/AndroidManifest.xml | 60 ++ .../src/main/assets/docs/index.html | 77 ++ .../src/main/assets/icon_day.png | Bin 0 -> 15407 bytes .../src/main/assets/icon_night.png | Bin 0 -> 16365 bytes .../plugins/aigemini}/GeminiBackend.kt | 191 +++- .../plugins/aigemini}/GeminiErrorFormatter.kt | 2 +- .../plugins/aigemini/GeminiPlugin.kt | 252 +++++ .../plugins/aigemini/GeminiSystemPrompt.kt | 82 ++ .../plugins/aigemini}/SecureApiKeyStore.kt | 4 +- .../aigemini/settings}/CatalogResult.kt | 9 +- .../aigemini/settings/GeminiCatalogGateway.kt | 116 +++ .../aigemini/settings}/GeminiKeyOnboarding.kt | 2 +- .../settings/GeminiSettingsFragment.kt | 632 +++++++++++++ .../settings/GeminiSettingsViewModel.kt | 247 +++++ .../aigemini/settings}/KeyVerification.kt | 12 +- .../src/main/res/drawable/ic_key_rejected.xml | 0 .../main/res/drawable/ic_key_unchecked.xml | 0 .../src/main/res/drawable/ic_key_verified.xml | 0 .../src/main/res/drawable/ic_visibility.xml | 0 .../main/res/drawable/ic_visibility_off.xml | 0 .../res/layout/fragment_gemini_settings.xml | 0 .../src/main/res/values-night/colors.xml | 36 + .../src/main/res/values/colors.xml | 40 + .../src/main/res/values/strings.xml | 58 ++ .../src/main/res/values/styles.xml | 38 + .../aigemini}/GeminiErrorFormatterTest.kt | 2 +- ai-backend-local/.gitignore | 3 + {ai-core => ai-backend-local}/BUILDING.md | 84 +- ai-backend-local/README.md | 60 ++ .../SUBMODULE_NOTES.md | 0 ai-backend-local/ai-backend-local.html | 122 +++ ai-backend-local/build.gradle.kts | 84 ++ ai-backend-local/gradle.properties | 10 + .../gradle/libs.versions.toml | 0 .../libs/llama-api.jar | Bin .../libs/v8/llama-v8-release.aar | Bin .../llama-api/.gitignore | 0 .../llama-api/build.gradle.kts | 0 .../llamacpp/api/ILlamaController.kt | 0 .../llama-impl/.gitignore | 0 .../llama-impl/build.gradle.kts | 0 .../llama-impl/proguard-rules.pro | 0 .../llama-impl/src/main/cpp/CMakeLists.txt | 0 .../llama-impl/src/main/cpp/llama-android.cpp | 0 .../java/android/llama/cpp/LLamaAndroid.kt | 0 ai-backend-local/proguard-rules.pro | 13 + .../scripts/rebuild-llama-aar.sh | 7 +- ai-backend-local/settings.gradle.kts | 44 + ai-backend-local/src/main/AndroidManifest.xml | 57 ++ .../src/main/assets/docs/index.html | 82 ++ ai-backend-local/src/main/assets/icon_day.png | Bin 0 -> 15407 bytes .../src/main/assets/icon_night.png | Bin 0 -> 16365 bytes .../androidide/plugins/ailocal}/ByteSize.kt | 2 +- .../plugins/ailocal}/GgufModelInspector.kt | 2 +- .../plugins/ailocal}/LocalLlmBackend.kt | 110 ++- .../plugins/ailocal/LocalLlmPlugin.kt | 255 +++++ .../plugins/ailocal/LocalSystemPrompt.kt | 67 ++ .../plugins/ailocal}/ModelLoadDiagnostics.kt | 2 +- .../plugins/ailocal}/ModelLoadMessages.kt | 4 +- .../plugins/ailocal}/UserFeedback.kt | 7 +- .../plugins/ailocal/model}/DeviceMemory.kt | 2 +- .../ailocal/model}/GgufFileInspector.kt | 8 +- .../ailocal/model}/GgufHeaderReader.kt | 4 +- .../plugins/ailocal/model}/ModelFileSource.kt | 2 +- .../ailocal/model}/ModelMemoryEstimator.kt | 15 +- .../plugins/ailocal/model}/ModelMemoryGate.kt | 2 +- .../settings/LocalLlmSettingsFragment.kt | 257 +++++ .../settings/LocalLlmSettingsViewModel.kt | 331 +++++++ .../settings}/MemoryWarningDialogFragment.kt | 23 +- .../ailocal/settings}/UserConfirmation.kt | 2 +- .../layout/fragment_local_llm_settings.xml | 0 .../src/main/res/values-night/colors.xml | 36 + .../src/main/res/values/colors.xml | 40 + .../src/main/res/values/strings.xml | 39 + .../src/main/res/values/styles.xml | 38 + .../plugins/ailocal}/ByteSizeTest.kt | 2 +- .../plugins/ailocal/LocalLlmBackendTest.kt | 86 ++ .../ailocal}/ModelLoadDiagnosticsTest.kt | 4 +- .../plugins/ailocal}/ModelLoadMessagesTest.kt | 4 +- .../subprojects/llama.cpp | 0 ai-core/README.md | 65 +- ai-core/ai-core.html | 107 +-- ai-core/build.gradle.kts | 77 +- ai-core/proguard-rules.pro | 8 - ai-core/settings.gradle.kts | 10 +- ai-core/src/main/AndroidManifest.xml | 10 +- ai-core/src/main/assets/docs/index.html | 45 +- .../androidide/plugins/aicore/AiBackend.kt | 69 +- .../androidide/plugins/aicore/AiCorePlugin.kt | 60 +- .../plugins/aicore/CancellableBackend.kt | 11 - .../plugins/aicore/LlmInferenceServiceImpl.kt | 51 +- ai-core/src/main/res/values/strings.xml | 26 +- .../plugins/aicore/AiCoreIntegrationTest.kt | 45 +- .../plugins/aicore/AiCorePluginTest.kt | 9 +- .../aicore/LlmInferenceServiceImplTest.kt | 102 ++ .../plugins/aicore/LocalLlmBackendTest.kt | 46 - 126 files changed, 4843 insertions(+), 4116 deletions(-) create mode 100644 ai-assistant/src/main/kotlin/com/itsaky/androidide/plugins/aiassistant/backends/BackendFragmentFactory.kt create mode 100644 ai-assistant/src/main/kotlin/com/itsaky/androidide/plugins/aiassistant/backends/BackendRegistry.kt delete mode 100644 ai-assistant/src/main/kotlin/com/itsaky/androidide/plugins/aiassistant/gemini/GeminiCatalogGateway.kt delete mode 100644 ai-assistant/src/main/kotlin/com/itsaky/androidide/plugins/aiassistant/security/SecureApiKeyStore.kt delete mode 100644 ai-assistant/src/main/kotlin/com/itsaky/androidide/plugins/aiassistant/util/ByteSize.kt delete mode 100644 ai-assistant/src/main/kotlin/com/itsaky/androidide/plugins/aiassistant/viewmodel/AiSettingsViewModel.kt delete mode 100644 ai-assistant/src/test/kotlin/com/itsaky/androidide/plugins/aiassistant/gemini/GeminiKeyOnboardingTest.kt delete mode 100644 ai-assistant/src/test/kotlin/com/itsaky/androidide/plugins/aiassistant/gemini/KeyVerificationTest.kt delete mode 100644 ai-assistant/src/test/kotlin/com/itsaky/androidide/plugins/aiassistant/memory/ModelMemoryEstimatorTest.kt delete mode 100644 ai-assistant/src/test/kotlin/com/itsaky/androidide/plugins/aiassistant/memory/ModelMemoryGateTest.kt delete mode 100644 ai-assistant/src/test/kotlin/com/itsaky/androidide/plugins/aiassistant/util/GgufFileInspectorTest.kt delete mode 100644 ai-assistant/src/test/kotlin/com/itsaky/androidide/plugins/aiassistant/util/GgufHeaderReaderTest.kt delete mode 100644 ai-assistant/src/test/kotlin/com/itsaky/androidide/plugins/aiassistant/util/GgufWriter.kt delete mode 100644 ai-assistant/src/test/kotlin/com/itsaky/androidide/plugins/aiassistant/viewmodel/AiSettingsViewModelMemoryTest.kt delete mode 100644 ai-assistant/src/test/kotlin/com/itsaky/androidide/plugins/aiassistant/viewmodel/AiSettingsViewModelVerifyTest.kt delete mode 100644 ai-assistant/src/test/kotlin/com/itsaky/androidide/plugins/aiassistant/viewmodel/UserConfirmationTest.kt create mode 100644 ai-backend-gemini/.gitignore create mode 100644 ai-backend-gemini/README.md create mode 100644 ai-backend-gemini/ai-backend-gemini.html create mode 100644 ai-backend-gemini/build.gradle.kts create mode 100644 ai-backend-gemini/gradle.properties create mode 100644 ai-backend-gemini/proguard-rules.pro create mode 100644 ai-backend-gemini/settings.gradle.kts create mode 100644 ai-backend-gemini/src/main/AndroidManifest.xml create mode 100644 ai-backend-gemini/src/main/assets/docs/index.html create mode 100644 ai-backend-gemini/src/main/assets/icon_day.png create mode 100644 ai-backend-gemini/src/main/assets/icon_night.png rename {ai-core/src/main/kotlin/com/itsaky/androidide/plugins/aicore => ai-backend-gemini/src/main/kotlin/com/itsaky/androidide/plugins/aigemini}/GeminiBackend.kt (81%) rename {ai-core/src/main/kotlin/com/itsaky/androidide/plugins/aicore => ai-backend-gemini/src/main/kotlin/com/itsaky/androidide/plugins/aigemini}/GeminiErrorFormatter.kt (99%) create mode 100644 ai-backend-gemini/src/main/kotlin/com/itsaky/androidide/plugins/aigemini/GeminiPlugin.kt create mode 100644 ai-backend-gemini/src/main/kotlin/com/itsaky/androidide/plugins/aigemini/GeminiSystemPrompt.kt rename {ai-core/src/main/kotlin/com/itsaky/androidide/plugins/aicore => ai-backend-gemini/src/main/kotlin/com/itsaky/androidide/plugins/aigemini}/SecureApiKeyStore.kt (97%) rename {ai-assistant/src/main/kotlin/com/itsaky/androidide/plugins/aiassistant/gemini => ai-backend-gemini/src/main/kotlin/com/itsaky/androidide/plugins/aigemini/settings}/CatalogResult.kt (64%) create mode 100644 ai-backend-gemini/src/main/kotlin/com/itsaky/androidide/plugins/aigemini/settings/GeminiCatalogGateway.kt rename {ai-assistant/src/main/kotlin/com/itsaky/androidide/plugins/aiassistant/gemini => ai-backend-gemini/src/main/kotlin/com/itsaky/androidide/plugins/aigemini/settings}/GeminiKeyOnboarding.kt (89%) create mode 100644 ai-backend-gemini/src/main/kotlin/com/itsaky/androidide/plugins/aigemini/settings/GeminiSettingsFragment.kt create mode 100644 ai-backend-gemini/src/main/kotlin/com/itsaky/androidide/plugins/aigemini/settings/GeminiSettingsViewModel.kt rename {ai-assistant/src/main/kotlin/com/itsaky/androidide/plugins/aiassistant/gemini => ai-backend-gemini/src/main/kotlin/com/itsaky/androidide/plugins/aigemini/settings}/KeyVerification.kt (89%) rename {ai-assistant => ai-backend-gemini}/src/main/res/drawable/ic_key_rejected.xml (100%) rename {ai-assistant => ai-backend-gemini}/src/main/res/drawable/ic_key_unchecked.xml (100%) rename {ai-assistant => ai-backend-gemini}/src/main/res/drawable/ic_key_verified.xml (100%) rename {ai-assistant => ai-backend-gemini}/src/main/res/drawable/ic_visibility.xml (100%) rename {ai-assistant => ai-backend-gemini}/src/main/res/drawable/ic_visibility_off.xml (100%) rename ai-assistant/src/main/res/layout/layout_settings_gemini_api.xml => ai-backend-gemini/src/main/res/layout/fragment_gemini_settings.xml (100%) create mode 100644 ai-backend-gemini/src/main/res/values-night/colors.xml create mode 100644 ai-backend-gemini/src/main/res/values/colors.xml create mode 100644 ai-backend-gemini/src/main/res/values/strings.xml create mode 100644 ai-backend-gemini/src/main/res/values/styles.xml rename {ai-core/src/test/kotlin/com/itsaky/androidide/plugins/aicore => ai-backend-gemini/src/test/kotlin/com/itsaky/androidide/plugins/aigemini}/GeminiErrorFormatterTest.kt (99%) create mode 100644 ai-backend-local/.gitignore rename {ai-core => ai-backend-local}/BUILDING.md (74%) create mode 100644 ai-backend-local/README.md rename {ai-core => ai-backend-local}/SUBMODULE_NOTES.md (100%) create mode 100644 ai-backend-local/ai-backend-local.html create mode 100644 ai-backend-local/build.gradle.kts create mode 100644 ai-backend-local/gradle.properties rename {ai-core => ai-backend-local}/gradle/libs.versions.toml (100%) rename {ai-core => ai-backend-local}/libs/llama-api.jar (100%) rename {ai-core => ai-backend-local}/libs/v8/llama-v8-release.aar (100%) rename {ai-core => ai-backend-local}/llama-api/.gitignore (100%) rename {ai-core => ai-backend-local}/llama-api/build.gradle.kts (100%) rename {ai-core => ai-backend-local}/llama-api/src/main/java/com/itsaky/androidide/llamacpp/api/ILlamaController.kt (100%) rename {ai-core => ai-backend-local}/llama-impl/.gitignore (100%) rename {ai-core => ai-backend-local}/llama-impl/build.gradle.kts (100%) rename {ai-core => ai-backend-local}/llama-impl/proguard-rules.pro (100%) rename {ai-core => ai-backend-local}/llama-impl/src/main/cpp/CMakeLists.txt (100%) rename {ai-core => ai-backend-local}/llama-impl/src/main/cpp/llama-android.cpp (100%) rename {ai-core => ai-backend-local}/llama-impl/src/main/java/android/llama/cpp/LLamaAndroid.kt (100%) create mode 100644 ai-backend-local/proguard-rules.pro rename {ai-core => ai-backend-local}/scripts/rebuild-llama-aar.sh (82%) create mode 100644 ai-backend-local/settings.gradle.kts create mode 100644 ai-backend-local/src/main/AndroidManifest.xml create mode 100644 ai-backend-local/src/main/assets/docs/index.html create mode 100644 ai-backend-local/src/main/assets/icon_day.png create mode 100644 ai-backend-local/src/main/assets/icon_night.png rename {ai-core/src/main/kotlin/com/itsaky/androidide/plugins/aicore => ai-backend-local/src/main/kotlin/com/itsaky/androidide/plugins/ailocal}/ByteSize.kt (96%) rename {ai-core/src/main/kotlin/com/itsaky/androidide/plugins/aicore => ai-backend-local/src/main/kotlin/com/itsaky/androidide/plugins/ailocal}/GgufModelInspector.kt (99%) rename {ai-core/src/main/kotlin/com/itsaky/androidide/plugins/aicore => ai-backend-local/src/main/kotlin/com/itsaky/androidide/plugins/ailocal}/LocalLlmBackend.kt (84%) create mode 100644 ai-backend-local/src/main/kotlin/com/itsaky/androidide/plugins/ailocal/LocalLlmPlugin.kt create mode 100644 ai-backend-local/src/main/kotlin/com/itsaky/androidide/plugins/ailocal/LocalSystemPrompt.kt rename {ai-core/src/main/kotlin/com/itsaky/androidide/plugins/aicore => ai-backend-local/src/main/kotlin/com/itsaky/androidide/plugins/ailocal}/ModelLoadDiagnostics.kt (99%) rename {ai-core/src/main/kotlin/com/itsaky/androidide/plugins/aicore => ai-backend-local/src/main/kotlin/com/itsaky/androidide/plugins/ailocal}/ModelLoadMessages.kt (93%) rename {ai-core/src/main/kotlin/com/itsaky/androidide/plugins/aicore => ai-backend-local/src/main/kotlin/com/itsaky/androidide/plugins/ailocal}/UserFeedback.kt (92%) rename {ai-assistant/src/main/kotlin/com/itsaky/androidide/plugins/aiassistant/memory => ai-backend-local/src/main/kotlin/com/itsaky/androidide/plugins/ailocal/model}/DeviceMemory.kt (96%) rename {ai-assistant/src/main/kotlin/com/itsaky/androidide/plugins/aiassistant/util => ai-backend-local/src/main/kotlin/com/itsaky/androidide/plugins/ailocal/model}/GgufFileInspector.kt (90%) rename {ai-assistant/src/main/kotlin/com/itsaky/androidide/plugins/aiassistant/util => ai-backend-local/src/main/kotlin/com/itsaky/androidide/plugins/ailocal/model}/GgufHeaderReader.kt (98%) rename {ai-assistant/src/main/kotlin/com/itsaky/androidide/plugins/aiassistant/util => ai-backend-local/src/main/kotlin/com/itsaky/androidide/plugins/ailocal/model}/ModelFileSource.kt (98%) rename {ai-assistant/src/main/kotlin/com/itsaky/androidide/plugins/aiassistant/memory => ai-backend-local/src/main/kotlin/com/itsaky/androidide/plugins/ailocal/model}/ModelMemoryEstimator.kt (91%) rename {ai-assistant/src/main/kotlin/com/itsaky/androidide/plugins/aiassistant/memory => ai-backend-local/src/main/kotlin/com/itsaky/androidide/plugins/ailocal/model}/ModelMemoryGate.kt (97%) create mode 100644 ai-backend-local/src/main/kotlin/com/itsaky/androidide/plugins/ailocal/settings/LocalLlmSettingsFragment.kt create mode 100644 ai-backend-local/src/main/kotlin/com/itsaky/androidide/plugins/ailocal/settings/LocalLlmSettingsViewModel.kt rename {ai-assistant/src/main/kotlin/com/itsaky/androidide/plugins/aiassistant/fragments => ai-backend-local/src/main/kotlin/com/itsaky/androidide/plugins/ailocal/settings}/MemoryWarningDialogFragment.kt (88%) rename {ai-assistant/src/main/kotlin/com/itsaky/androidide/plugins/aiassistant/viewmodel => ai-backend-local/src/main/kotlin/com/itsaky/androidide/plugins/ailocal/settings}/UserConfirmation.kt (97%) rename ai-assistant/src/main/res/layout/layout_settings_local_llm.xml => ai-backend-local/src/main/res/layout/fragment_local_llm_settings.xml (100%) create mode 100644 ai-backend-local/src/main/res/values-night/colors.xml create mode 100644 ai-backend-local/src/main/res/values/colors.xml create mode 100644 ai-backend-local/src/main/res/values/strings.xml create mode 100644 ai-backend-local/src/main/res/values/styles.xml rename {ai-core/src/test/kotlin/com/itsaky/androidide/plugins/aicore => ai-backend-local/src/test/kotlin/com/itsaky/androidide/plugins/ailocal}/ByteSizeTest.kt (96%) create mode 100644 ai-backend-local/src/test/kotlin/com/itsaky/androidide/plugins/ailocal/LocalLlmBackendTest.kt rename {ai-core/src/test/kotlin/com/itsaky/androidide/plugins/aicore => ai-backend-local/src/test/kotlin/com/itsaky/androidide/plugins/ailocal}/ModelLoadDiagnosticsTest.kt (98%) rename {ai-core/src/test/kotlin/com/itsaky/androidide/plugins/aicore => ai-backend-local/src/test/kotlin/com/itsaky/androidide/plugins/ailocal}/ModelLoadMessagesTest.kt (96%) rename {ai-core => ai-backend-local}/subprojects/llama.cpp (100%) delete mode 100644 ai-core/src/main/kotlin/com/itsaky/androidide/plugins/aicore/CancellableBackend.kt delete mode 100644 ai-core/src/test/kotlin/com/itsaky/androidide/plugins/aicore/LocalLlmBackendTest.kt diff --git a/.gitmodules b/.gitmodules index ad9dd4f3..6176e6bc 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,4 +1,4 @@ [submodule "ai-core/subprojects/llama.cpp"] - path = ai-core/subprojects/llama.cpp + path = ai-backend-local/subprojects/llama.cpp url = https://github.com/appdevforall/llama.cpp.git branch = androidide-custom diff --git a/README.md b/README.md index ab158a3a..ac9d14eb 100644 --- a/README.md +++ b/README.md @@ -22,8 +22,10 @@ See the official [plugin documentation](https://www.appdevforall.org/codeonthego | [`compose-preview/`](compose-preview/) | Renders Jetpack Compose `@Preview` functions on-device — no full app build or run. | | [`ai-literacy-course/`](ai-literacy-course/) | Bundles Learn AI Anywhere's offline "Introduction to AI" course (26 videos + interactive activities) and plays it full-screen, fully offline. | | [`layout-editor/`](layout-editor/) | Visual drag-and-drop editor for Android XML layouts. | -| [`ai-core/`](ai-core/) | Shared on-device LLM inference backend (bundled llama.cpp AAR) plus a Gemini API backend, exposed to other plugins as a runtime service. | -| [`ai-assistant/`](ai-assistant/) | In-IDE AI chat assistant with tool calling; talks to `ai-core` for inference over local or Gemini models. | +| [`ai-core/`](ai-core/) | Shared LLM inference **router**, exposed to other plugins as a runtime service. Ships no model — install at least one backend plugin below. | +| [`ai-backend-local/`](ai-backend-local/) | On-device `.gguf` inference backend for `ai-core` (bundled llama.cpp AAR). Registers as `local`; needs no network. | +| [`ai-backend-gemini/`](ai-backend-gemini/) | Google Gemini API inference backend for `ai-core`. Registers as `gemini`; needs an API key and network access. | +| [`ai-assistant/`](ai-assistant/) | In-IDE AI chat assistant with tool calling; talks to `ai-core`, which routes to whichever backend plugin is installed. | | [`flutter-template/`](flutter-template/) | Adds Flutter starter project templates (Basic, BLoC, Provider, GetX, Riverpod) to the New Project screen. | | [`code-suggestions-plugin/`](code-suggestions-plugin/) | Inline ghost-text code completions powered by AI. | | [`speech-to-text-plugin/`](speech-to-text-plugin/) | Voice-to-code: converts speech to code with AI generation. | diff --git a/ai-assistant/ai-assistant.html b/ai-assistant/ai-assistant.html index dd291e3f..4d853852 100644 --- a/ai-assistant/ai-assistant.html +++ b/ai-assistant/ai-assistant.html @@ -110,7 +110,7 @@

Build

cd ../ai-assistant && ./gradlew assemblePlugin

Outputs land at ai-core/build/plugin/ai-core.cgp and ai-assistant/build/plugin/ai-assistant.cgp. See - ../ai-core/BUILDING.md for full prerequisites.

+ ../ai-backend-local/BUILDING.md for full prerequisites.

Install & configure