diff --git a/AGENTS.md b/AGENTS.md index f7b3a04..ca58222 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -35,7 +35,7 @@ When a developer says *use the nova_dev skill to setup and build the app* or Nova is a Flutter-based mobile AI assistant that: -- Runs AI models entirely on-device using `flutter_gemma` +- Runs AI models entirely on-device using `flutter_edge_ai` (Flutter Edge AI) - Supports multiple inference engines (LiteRtLm, MediaPipe) - Provides voice input, screen capture, and tool execution capabilities - Uses RAG (Retrieval-Augmented Generation) with local memory @@ -57,9 +57,9 @@ Nova is a Flutter-based mobile AI assistant that: | Package | Version | Purpose | |---------|---------|---------| -| `flutter_gemma` | ^1.11.0 | Core Gemma inference engine | -| `flutter_gemma_litertlm` | ^1.8.4 | LiteRT LM inference backend | -| `flutter_gemma_mediapipe` | ^1.0.7 | MediaPipe inference backend | +| `flutter_edge_ai` | ^2.0.0 | Core on-device inference engine | +| `flutter_edge_ai_litertlm` | ^1.8.7 | LiteRT LM inference backend | +| `flutter_edge_ai_mediapipe` | ^1.0.9 | MediaPipe inference backend | ### Storage and Persistence @@ -409,7 +409,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; // 3. Package imports -import 'package:flutter_gemma/flutter_gemma.dart'; +import 'package:flutter_edge_ai/flutter_edge_ai.dart'; import 'package:shared_preferences/shared_preferences.dart'; // 4. Project imports diff --git a/CHANGELOG.md b/CHANGELOG.md index cad7b55..d193c9b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Changed +- Migrate on-device inference from discontinued `flutter_gemma` packages to Flutter Edge AI 2.0 (`flutter_edge_ai`, `flutter_edge_ai_litertlm`, `flutter_edge_ai_mediapipe`, `flutter_edge_ai_speech`). Raise minimum Flutter SDK to 3.44. ## [0.4.8] - 2026-09-22 diff --git a/README.md b/README.md index 748ce23..a5a663d 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ Also available to other agents via [`.agents/skills/nova-dev`](.agents/skills/no ## Features -- **On-device AI** — Gemma / LiteRT via `flutter_gemma` +- **On-device AI** — Gemma / LiteRT via `flutter_edge_ai` (Flutter Edge AI) - **Multi-model** — SmolLM, FastVLM, Gemma 3 1B, Gemma 4 E2B + custom import - **Voice** — speech-to-text input - **Screen awareness** — MediaProjection screenshots for vision models @@ -91,7 +91,7 @@ There is **no** `android.backup/` — that stale tree was removed. ## Architecture (brief) 1. UI → `ModelOrchestrator.processMessage` -2. RAG + model select + `flutter_gemma` stream +2. RAG + model select + `flutter_edge_ai` stream 3. Tool calls → Dart services or Android `ToolExecutor` 4. Idle / lifecycle unload **after** streaming completes @@ -133,6 +133,6 @@ MIT — see [LICENSE](LICENSE). ## Acknowledgments - [Flutter](https://flutter.dev/) -- [flutter_gemma](https://pub.dev/packages/flutter_gemma) +- [flutter_edge_ai](https://pub.dev/packages/flutter_edge_ai) - [Gemma](https://ai.google.dev/gemma) - [HuggingFace](https://huggingface.co/) diff --git a/docs/architecture.md b/docs/architecture.md index df9806b..a7e39b4 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -12,7 +12,7 @@ UI (screens / widgets) │ ModelOrchestrator ←── MemoryService (RAG), MCP, Tasks, Notes │ - flutter_gemma / LiteRT-LM + flutter_edge_ai / LiteRT-LM │ Platform channels → Android (tools, screenshot, assistant key) ``` diff --git a/lib/main.dart b/lib/main.dart index 13376dd..0285488 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,9 +1,10 @@ import 'dart:async'; import 'package:flutter/material.dart'; -import 'package:flutter_gemma/flutter_gemma.dart'; -import 'package:flutter_gemma_litertlm/flutter_gemma_litertlm.dart'; -import 'package:flutter_gemma_mediapipe/flutter_gemma_mediapipe.dart'; +import 'package:flutter_edge_ai/flutter_edge_ai.dart'; +import 'package:flutter_edge_ai_litertlm/flutter_edge_ai_litertlm.dart'; +import 'package:flutter_edge_ai_mediapipe/flutter_edge_ai_mediapipe.dart'; +import 'package:flutter_edge_ai_speech/flutter_edge_ai_speech.dart'; import 'package:nova_assistant/services/model_orchestrator.dart'; import 'package:nova_assistant/services/model_manager.dart'; import 'package:nova_assistant/services/image_generation_service.dart'; @@ -55,8 +56,9 @@ void main() async { ); // #endregion - await FlutterGemma.initialize( + await FlutterEdgeAi.initialize( inferenceEngines: const [LiteRtLmEngine(), MediaPipeEngine()], + ttsBackends: const [LiteRtTtsBackend()], maxDownloadRetries: 3, ); diff --git a/lib/models/external_tool.dart b/lib/models/external_tool.dart index 2ec3fe9..7b7cc70 100644 --- a/lib/models/external_tool.dart +++ b/lib/models/external_tool.dart @@ -1,7 +1,7 @@ import 'dart:convert'; import 'dart:io'; -import 'package:flutter_gemma/flutter_gemma.dart'; +import 'package:flutter_edge_ai/flutter_edge_ai.dart'; enum ExternalToolType { http, local, mcp } diff --git a/lib/models/litert_model_catalog.dart b/lib/models/litert_model_catalog.dart index 556ee6b..88ea0fd 100644 --- a/lib/models/litert_model_catalog.dart +++ b/lib/models/litert_model_catalog.dart @@ -1,4 +1,4 @@ -import 'package:flutter_gemma/flutter_gemma.dart'; +import 'package:flutter_edge_ai/flutter_edge_ai.dart'; import 'package:nova_assistant/models/model_info.dart'; import 'package:nova_assistant/services/huggingface_hub_service.dart'; diff --git a/lib/models/model_info.dart b/lib/models/model_info.dart index 364bff3..cb0da2a 100644 --- a/lib/models/model_info.dart +++ b/lib/models/model_info.dart @@ -1,4 +1,4 @@ -import 'package:flutter_gemma/flutter_gemma.dart'; +import 'package:flutter_edge_ai/flutter_edge_ai.dart'; import 'package:nova_assistant/models/litert_model_catalog.dart'; enum NovaModel { diff --git a/lib/models/uncensored_model_catalog.dart b/lib/models/uncensored_model_catalog.dart index 2d2b597..b5c018b 100644 --- a/lib/models/uncensored_model_catalog.dart +++ b/lib/models/uncensored_model_catalog.dart @@ -1,4 +1,4 @@ -import 'package:flutter_gemma/flutter_gemma.dart'; +import 'package:flutter_edge_ai/flutter_edge_ai.dart'; import 'package:nova_assistant/services/huggingface_hub_service.dart'; /// Curated uncensored chat models that ship LiteRT-native assets diff --git a/lib/screens/assistant_screen.dart b/lib/screens/assistant_screen.dart index e8934e3..b2bc796 100644 --- a/lib/screens/assistant_screen.dart +++ b/lib/screens/assistant_screen.dart @@ -28,7 +28,7 @@ import 'package:nova_assistant/services/user_preferences_service.dart'; import 'package:nova_assistant/services/mcp_service.dart'; import 'package:nova_assistant/platform/screenshot_service.dart'; import 'package:nova_assistant/platform/overlay_service.dart'; -import 'package:flutter_gemma/flutter_gemma.dart'; +import 'package:flutter_edge_ai/flutter_edge_ai.dart'; import 'package:nova_assistant/tools/tool_definitions.dart'; import 'package:nova_assistant/widgets/in_chat_search_bar.dart'; import 'package:nova_assistant/screens/chat_history_screen.dart'; diff --git a/lib/screens/custom_model_import_sheet.dart b/lib/screens/custom_model_import_sheet.dart index 7aae2b8..04ce456 100644 --- a/lib/screens/custom_model_import_sheet.dart +++ b/lib/screens/custom_model_import_sheet.dart @@ -1,6 +1,6 @@ import 'package:file_picker/file_picker.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_gemma/flutter_gemma.dart'; +import 'package:flutter_edge_ai/flutter_edge_ai.dart'; import 'package:nova_assistant/models/model_info.dart'; import 'package:nova_assistant/services/model_manager.dart'; import 'package:nova_assistant/utils/message_limits.dart'; diff --git a/lib/screens/settings_screen.dart b/lib/screens/settings_screen.dart index 3b52625..5e25509 100644 --- a/lib/screens/settings_screen.dart +++ b/lib/screens/settings_screen.dart @@ -4,7 +4,7 @@ import 'dart:io'; import 'package:file_picker/file_picker.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_gemma/flutter_gemma.dart'; +import 'package:flutter_edge_ai/flutter_edge_ai.dart'; import 'package:package_info_plus/package_info_plus.dart'; import 'package:path/path.dart' as p; import 'package:path_provider/path_provider.dart'; diff --git a/lib/services/huggingface_hub_service.dart b/lib/services/huggingface_hub_service.dart index 75716e9..0577b4e 100644 --- a/lib/services/huggingface_hub_service.dart +++ b/lib/services/huggingface_hub_service.dart @@ -2,7 +2,7 @@ import 'dart:convert'; import 'dart:io'; import 'package:flutter/foundation.dart'; -import 'package:flutter_gemma/flutter_gemma.dart'; +import 'package:flutter_edge_ai/flutter_edge_ai.dart'; import 'package:nova_assistant/services/model_manager.dart'; /// A Hugging Face Hub model search hit. diff --git a/lib/services/mcp_service.dart b/lib/services/mcp_service.dart index 7627291..9c4b868 100644 --- a/lib/services/mcp_service.dart +++ b/lib/services/mcp_service.dart @@ -3,7 +3,7 @@ import 'dart:convert'; import 'dart:io'; import 'package:flutter/foundation.dart'; -import 'package:flutter_gemma/flutter_gemma.dart' as gemma; +import 'package:flutter_edge_ai/flutter_edge_ai.dart' as gemma; import 'package:path_provider/path_provider.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:uuid/uuid.dart'; diff --git a/lib/services/model_manager.dart b/lib/services/model_manager.dart index 9da8ded..c63f5f7 100644 --- a/lib/services/model_manager.dart +++ b/lib/services/model_manager.dart @@ -4,7 +4,7 @@ import 'dart:io'; import 'package:crypto/crypto.dart'; import 'package:flutter/foundation.dart'; -import 'package:flutter_gemma/flutter_gemma.dart'; +import 'package:flutter_edge_ai/flutter_edge_ai.dart'; import 'package:path_provider/path_provider.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:path/path.dart' as p; @@ -815,7 +815,7 @@ class ModelManager { } try { - final builder = FlutterGemma.installModel( + final builder = FlutterEdgeAi.installModel( modelType: modelType, fileType: fileType, ).fromFile(canonicalPath); @@ -1081,12 +1081,12 @@ class ModelManager { // "Remove" only clears prefs and leaves multi-GB weights on device. final deleted = await _deleteModelFile(model.fileName); try { - await FlutterGemma.uninstallModel(modelId); + await FlutterEdgeAi.uninstallModel(modelId); } catch (e) { - debugPrint('ModelManager: FlutterGemma.uninstallModel: $e'); + debugPrint('ModelManager: FlutterEdgeAi.uninstallModel: $e'); } try { - await FlutterGemma.uninstallModel(model.fileName); + await FlutterEdgeAi.uninstallModel(model.fileName); } catch (_) {} _installedModels.removeWhere((m) => m.id == modelId); _pathCache.remove(model.fileName); @@ -1112,9 +1112,9 @@ class ModelManager { final deleted = await _deleteModelFile(customModel.fileName); try { - await FlutterGemma.uninstallModel(customModel.fileName); + await FlutterEdgeAi.uninstallModel(customModel.fileName); } catch (e) { - debugPrint('ModelManager: FlutterGemma.uninstallModel custom: $e'); + debugPrint('ModelManager: FlutterEdgeAi.uninstallModel custom: $e'); } _customModels.removeWhere((m) => m.id == modelId); _pathCache.remove(customModel.fileName); @@ -1238,7 +1238,7 @@ class ModelManager { /// Register a model already on disk (no download). /// /// If [deferInstall] is false (default), registers with flutter_gemma - /// immediately by calling `FlutterGemma.installModel().fromFile().install()`. + /// immediately by calling `FlutterEdgeAi.installModel().fromFile().install()`. /// This makes the model available for inference. /// /// If [deferInstall] is true, skips the flutter_gemma registration and just @@ -1294,7 +1294,7 @@ class ModelManager { int registeredSize = actualSize; try { - await FlutterGemma.installModel( + await FlutterEdgeAi.installModel( modelType: modelType, fileType: fileType, ).fromFile(filePath).install(); @@ -1311,7 +1311,7 @@ class ModelManager { if (altPath != null && altPath != filePath) { try { registeredSize = await File(altPath).length(); - await FlutterGemma.installModel( + await FlutterEdgeAi.installModel( modelType: modelType, fileType: fileType, ).fromFile(altPath).install(); diff --git a/lib/services/model_orchestrator.dart b/lib/services/model_orchestrator.dart index 278eca2..29e48f5 100644 --- a/lib/services/model_orchestrator.dart +++ b/lib/services/model_orchestrator.dart @@ -4,7 +4,7 @@ import 'dart:io'; import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; -import 'package:flutter_gemma/flutter_gemma.dart'; +import 'package:flutter_edge_ai/flutter_edge_ai.dart'; import 'package:path_provider/path_provider.dart'; import 'package:path/path.dart' as p; import 'package:shared_preferences/shared_preferences.dart'; @@ -1008,7 +1008,7 @@ class ModelOrchestrator { data: { 'activeModelType': _activeModelType?.name, 'hasActiveModel': _activeModel != null, - 'flutterHasActive': FlutterGemma.hasActiveModel(), + 'flutterHasActive': FlutterEdgeAi.hasActiveModel(), }, ); // #endregion @@ -1037,7 +1037,7 @@ class ModelOrchestrator { message: 'Idle release finished', data: { 'elapsedMs': DateTime.now().millisecondsSinceEpoch - releaseStarted, - 'flutterHasActive': FlutterGemma.hasActiveModel(), + 'flutterHasActive': FlutterEdgeAi.hasActiveModel(), }, ); // #endregion @@ -1140,7 +1140,7 @@ class ModelOrchestrator { (modelToLoad != null ? _loadTimeoutFor(modelToLoad) : const Duration(seconds: 120)); - final future = FlutterGemma.getActiveModel( + final future = FlutterEdgeAi.getActiveModel( maxTokens: tokenLimit, preferredBackend: preferredBackend, supportImage: supportImage, @@ -1590,9 +1590,9 @@ class ModelOrchestrator { // Clear flutter_gemma's internal state whenever we need a fresh engine // (different model OR vision support mismatch). - if (FlutterGemma.hasActiveModel()) { + if (FlutterEdgeAi.hasActiveModel()) { try { - await FlutterGemma.clearActiveInferenceIdentity(); + await FlutterEdgeAi.clearActiveInferenceIdentity(); } catch (e) { debugPrint('Error clearing active identity: $e'); } @@ -2044,9 +2044,9 @@ class ModelOrchestrator { // Clear BEFORE register — clearing after install() leaves no active model. await _teardownActiveModel(); - if (FlutterGemma.hasActiveModel()) { + if (FlutterEdgeAi.hasActiveModel()) { try { - await FlutterGemma.clearActiveInferenceIdentity(); + await FlutterEdgeAi.clearActiveInferenceIdentity(); } catch (_) {} } @@ -2073,7 +2073,7 @@ class ModelOrchestrator { 'fileName': customModel.fileName, 'backend': backend.name, 'totalMemMb': total, - 'hasActive': FlutterGemma.hasActiveModel(), + 'hasActive': FlutterEdgeAi.hasActiveModel(), }, runId: 'post-fix', ); @@ -4307,9 +4307,9 @@ class ModelOrchestrator { } Future _clearActiveInferenceIdentity() async { - if (!FlutterGemma.hasActiveModel()) return; + if (!FlutterEdgeAi.hasActiveModel()) return; try { - await FlutterGemma.clearActiveInferenceIdentity(); + await FlutterEdgeAi.clearActiveInferenceIdentity(); } catch (e) { debugPrint('Error clearing active inference identity: $e'); } diff --git a/lib/services/model_update_service.dart b/lib/services/model_update_service.dart index 254b6da..41882b6 100644 --- a/lib/services/model_update_service.dart +++ b/lib/services/model_update_service.dart @@ -2,7 +2,7 @@ import 'dart:async'; import 'dart:convert'; import 'package:flutter/foundation.dart'; -import 'package:flutter_gemma/flutter_gemma.dart'; +import 'package:flutter_edge_ai/flutter_edge_ai.dart'; import 'package:http/http.dart' as http; import 'package:shared_preferences/shared_preferences.dart'; import 'package:nova_assistant/models/litert_model_catalog.dart'; diff --git a/lib/services/parallel_session_manager.dart b/lib/services/parallel_session_manager.dart index 6b1b612..1fe5cbf 100644 --- a/lib/services/parallel_session_manager.dart +++ b/lib/services/parallel_session_manager.dart @@ -1,7 +1,7 @@ import 'dart:async'; import 'package:flutter/foundation.dart'; -import 'package:flutter_gemma/flutter_gemma.dart'; +import 'package:flutter_edge_ai/flutter_edge_ai.dart'; import 'package:nova_assistant/models/model_info.dart'; import 'package:nova_assistant/services/model_orchestrator.dart'; import 'package:nova_assistant/services/platform_adaptation_service.dart'; @@ -290,11 +290,11 @@ class ParallelSessionManager { /// Get or create a model for inference Future _getOrCreateModel(NovaModel model) async { try { - if (!FlutterGemma.hasActiveModel()) { + if (!FlutterEdgeAi.hasActiveModel()) { return null; } - return await FlutterGemma.getActiveModel( + return await FlutterEdgeAi.getActiveModel( maxTokens: _tokenLimitFor(model), preferredBackend: PreferredBackend.gpu, supportImage: model.hasVision, diff --git a/lib/services/platform_adaptation_service.dart b/lib/services/platform_adaptation_service.dart index 41aaed9..c45dbf2 100644 --- a/lib/services/platform_adaptation_service.dart +++ b/lib/services/platform_adaptation_service.dart @@ -1,6 +1,6 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; -import 'package:flutter_gemma/flutter_gemma.dart'; +import 'package:flutter_edge_ai/flutter_edge_ai.dart'; import 'package:nova_assistant/models/model_info.dart'; import 'package:nova_assistant/services/memory_diagnostics_service.dart'; diff --git a/lib/services/session_history_reinjection.dart b/lib/services/session_history_reinjection.dart index d042038..25eab47 100644 --- a/lib/services/session_history_reinjection.dart +++ b/lib/services/session_history_reinjection.dart @@ -1,4 +1,4 @@ -import 'package:flutter_gemma/flutter_gemma.dart'; +import 'package:flutter_edge_ai/flutter_edge_ai.dart'; import 'package:nova_assistant/models/chat_message.dart'; import 'package:nova_assistant/models/model_info.dart'; import 'package:nova_assistant/utils/message_limits.dart'; diff --git a/lib/services/tts_service.dart b/lib/services/tts_service.dart index d0a1e42..07f7d85 100644 --- a/lib/services/tts_service.dart +++ b/lib/services/tts_service.dart @@ -2,12 +2,11 @@ import 'dart:async'; import 'dart:typed_data'; import 'package:flutter/foundation.dart'; -import 'package:flutter_gemma/flutter_gemma.dart'; -import 'package:flutter_gemma_speech/flutter_gemma_speech.dart'; +import 'package:flutter_edge_ai/flutter_edge_ai.dart'; import 'package:just_audio/just_audio.dart'; import 'package:shared_preferences/shared_preferences.dart'; -/// Speaks assistant responses via on-device TTS (Matcha via flutter_gemma). +/// Speaks assistant responses via on-device TTS (Matcha via Flutter Edge AI). // ignore_for_file: experimental_member_use class TtsService { static TtsService? _instance; @@ -35,12 +34,6 @@ class TtsService { final prefs = await SharedPreferences.getInstance(); _enabled = prefs.getBool(_enabledKey) ?? true; - try { - await FlutterGemma.initialize(ttsBackends: [LiteRtTtsBackend()]); - } on Exception catch (e) { - debugPrint('TtsService: backend init failed: $e'); - } - _playerStateSub = _player.playerStateStream.listen((state) { _speaking = state.playing; }); @@ -65,7 +58,7 @@ class TtsService { try { await _ensureModelInstalled(); - final synth = await FlutterGemma.getActiveTts(); + final synth = await FlutterEdgeAi.getActiveTts(); final pcm = await synth.synthesize(cleaned); await _playPcm(pcm, synth.sampleRate); await synth.close(); @@ -84,7 +77,7 @@ class TtsService { final prefs = await SharedPreferences.getInstance(); if (prefs.getBool(_modelInstalledKey) ?? false) { try { - await FlutterGemma.getActiveTts(); + await FlutterEdgeAi.getActiveTts(); return; } on Exception { await prefs.setBool(_modelInstalledKey, false); @@ -92,7 +85,7 @@ class TtsService { } try { - await FlutterGemma.installTts() + await FlutterEdgeAi.installTts() .fromNetwork(_ttsModelUrl) .ofType(TtsModelType.matcha) .install(); diff --git a/lib/tools/tool_definitions.dart b/lib/tools/tool_definitions.dart index e60b79f..e8cda7e 100644 --- a/lib/tools/tool_definitions.dart +++ b/lib/tools/tool_definitions.dart @@ -1,4 +1,4 @@ -import 'package:flutter_gemma/flutter_gemma.dart'; +import 'package:flutter_edge_ai/flutter_edge_ai.dart'; import 'package:nova_assistant/services/mcp_service.dart'; import 'package:nova_assistant/services/shizuku_service.dart'; diff --git a/pubspec.yaml b/pubspec.yaml index cd37cdc..9d9abb8 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -5,16 +5,16 @@ version: 0.4.8+7 environment: sdk: '>=3.13.0-282.1.beta <4.0.0' - flutter: '>=3.17.0-0.1.pre' + flutter: '>=3.44.0' dependencies: flutter: sdk: flutter - # AI Inference — core + engines - flutter_gemma: ^1.11.0 - flutter_gemma_litertlm: ^1.8.4 - flutter_gemma_mediapipe: ^1.0.7 + # AI Inference — core + engines (Flutter Edge AI 2.0) + flutter_edge_ai: ^2.0.0 + flutter_edge_ai_litertlm: ^1.8.7 + flutter_edge_ai_mediapipe: ^1.0.9 # Permissions permission_handler: ^13.0.2 @@ -58,7 +58,7 @@ dependencies: # Home Screen Widgets home_widget: ^0.9.4 syncfusion_flutter_pdf: ^34.2.8 - flutter_gemma_speech: ^0.5.2 + flutter_edge_ai_speech: ^0.5.3 url_launcher: ^6.3.2 connectivity_plus: ^7.3.1 diff --git a/test/models/custom_model_copy_with_test.dart b/test/models/custom_model_copy_with_test.dart index aee821d..d742b4f 100644 --- a/test/models/custom_model_copy_with_test.dart +++ b/test/models/custom_model_copy_with_test.dart @@ -1,6 +1,6 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:nova_assistant/models/model_info.dart'; -import 'package:flutter_gemma/flutter_gemma.dart'; +import 'package:flutter_edge_ai/flutter_edge_ai.dart'; void main() { group('CustomModel.copyWith', () { diff --git a/test/services/huggingface_hub_service_test.dart b/test/services/huggingface_hub_service_test.dart index c09ec15..95b02c1 100644 --- a/test/services/huggingface_hub_service_test.dart +++ b/test/services/huggingface_hub_service_test.dart @@ -1,4 +1,4 @@ -import 'package:flutter_gemma/flutter_gemma.dart'; +import 'package:flutter_edge_ai/flutter_edge_ai.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:nova_assistant/models/litert_model_catalog.dart'; import 'package:nova_assistant/models/model_info.dart';