Repository navigation
chore: migrate to Flutter Edge AI 2.0 #13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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()], | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟠 High · Core services remain uninitialized When TTS backend registration or initialization throws during startup, Handle TTS initialization failure separately so model and service initialization can continue. Also at Prompt for AI agentsIn `lib/main.dart` at line 61:
**Core services remain uninitialized**
When TTS backend registration or initialization throws during startup, `FlutterEdgeAi.initialize` propagates the error into `main`'s shared startup catch, which skips `ModelManager.initialize`, `_repairModels`, and the remaining service initialization; the app launches without its normal model and core services.
Handle TTS initialization failure separately so model and service initialization can continue.
Also at `lib/main.dart:62`.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. CRITICAL: TTS backend registration failure propagates and blocks startup The Handle TTS initialization separately so model and service initialization can continue even if TTS fails. Reply with |
||
| maxDownloadRetries: 3, | ||
| ); | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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). | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. SUGGESTION: Comment still references old package name The updated comment says Reply with |
||
| /// | ||
| /// 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(); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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: { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. SUGGESTION: Comment references old package name The debug log at line 1011 shows Reply with
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @kilocode-bot fix it
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I couldn't apply this fix automatically this time. I could not start this fix because the account needs at least $1 in available credits. Next steps:
Technical details
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. One or more Cloud Agent sessions failed:
|
||
| '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<void> _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'); | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CRITICAL: TTS initialization failure skips all core service initialization
If
FlutterEdgeAi.initialize()throws (e.g., TTS backend registration fails), the entire try block (lines 42-98) fails and the catch at line 96 only logs the error.ModelManager.instance.initialize(),_repairModels(), and allFuture.waitservice initializations are never executed. The app launches without models, memory, tasks, notes, notifications, TTS, MCP, etc.Wrap the
FlutterEdgeAi.initializecall in its own try-catch so failures don't block the rest of startup, or move TTS backend registration to a separate deferred initialization.Reply with
@kilocode-bot fix itto have Kilo Code address this issue.