@tduncan / Cortana / commits / 242474c

fix: integrate LiteRtLmEngine for on-device inference and update ScrollView cache configuration

abdulmominsakib committed Jun 17, 2026 at 14:59 UTC 242474cf59bce26c1c9821db45e30eac90b3bed8
7 files changed +27 -9
lib/features/chat/data/mcp_client.dart
+2
@@ -1,3 +1,5 @@
1 +// ignore_for_file: prefer_initializing_formals
2 +
3 import 'dart:async';
4 import 'dart:convert';
5
lib/features/chat/data/mcp_server_manager.dart
+2
@@ -1,3 +1,5 @@
1 +// ignore_for_file: prefer_initializing_formals
2 +
3 import 'mcp_client.dart';
4
5 const exampleMcpServerLabel = 'Example MCP';
lib/features/chat/views/chat_screen.dart
+2 -1
@@ -2,6 +2,7 @@ import 'dart:convert';
2 import 'dart:ui';
3
4 import 'package:flutter/material.dart';
5 +import 'package:flutter/rendering.dart';
6 import 'package:flutter/services.dart';
7 import 'package:flutter_riverpod/flutter_riverpod.dart';
8 import 'package:go_router/go_router.dart';
@@ -1388,7 +1389,7 @@ class _MessageList extends StatelessWidget {
1389
1390 return ListView.builder(
1391 controller: scrollController,
1391 - cacheExtent: 1000,
1392 + scrollCacheExtent: const ScrollCacheExtent.pixels(1000),
1393 padding: EdgeInsets.only(
1394 top: 16,
1395 bottom: 120 + (hasSmartReplies ? 64 : 0) + bottomInset,
lib/features/on_device/data/on_device_gemma_service.dart
+4 -2
@@ -2,6 +2,7 @@ import 'dart:io';
2
3 import 'package:flutter_gemma/flutter_gemma.dart';
4 import 'package:flutter_gemma/core/domain/model_source.dart';
5 +import 'package:flutter_gemma_litertlm/flutter_gemma_litertlm.dart';
6 import 'package:path_provider/path_provider.dart';
7
8 import '../../../core/logger/app_logger.dart';
@@ -20,6 +21,7 @@ class OnDeviceGemmaService {
21
22 static Future<void> initialize({String? huggingFaceToken}) async {
23 await FlutterGemma.initialize(
24 + inferenceEngines: const [LiteRtLmEngine()],
25 huggingFaceToken: huggingFaceToken,
26 maxDownloadRetries: 10,
27 );
@@ -60,7 +62,7 @@ class OnDeviceGemmaService {
62 final installed = await FlutterGemma.listInstalledModels();
63 final installedSet = installed.toSet();
64 final installedIds = <String>[];
63 -
65 +
66 for (final model in OnDeviceModel.curatedModels) {
67 if (installedSet.contains(model.fileName)) {
68 installedIds.add(model.id);
@@ -118,7 +120,7 @@ class OnDeviceGemmaService {
120 (m) => m.id == modelId,
121 orElse: () => throw Exception('Model not found: $modelId'),
122 );
121 -
123 +
124 final spec = InferenceModelSpec(
125 name: model.fileName,
126 modelSource: ModelSource.network(model.huggingFaceUrl),
pubspec.lock
+8
@@ -470,6 +470,14 @@ packages:
470 url: "https://pub.dev"
471 source: hosted
472 version: "1.0.0"
473 + flutter_gemma_litertlm:
474 + dependency: "direct main"
475 + description:
476 + name: flutter_gemma_litertlm
477 + sha256: "6b801403f1f682b699dbf31b485bddba2692296a894b7f23f1c78f171fc62fa3"
478 + url: "https://pub.dev"
479 + source: hosted
480 + version: "1.0.0"
481 flutter_lints:
482 dependency: "direct dev"
483 description:
pubspec.yaml
+5 -3
@@ -16,10 +16,11 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev
16 # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
17 # In Windows, build-name is used as the major, minor, and patch parts
18 # of the product and file versions while build-number is used as the build suffix.
19 -version: 1.4.0+43
19 +version: 1.4.0+44
20
21 environment:
22 - sdk: ">=3.11.0 <4.0.0"
22 + sdk: ">=3.12.0 <4.0.0"
23 + flutter: ">=3.44.0"
24
25 # Dependencies specify other packages that your package needs in order to work.
26 # To automatically upgrade your package dependencies to the latest versions
@@ -59,7 +60,8 @@ dependencies:
60 objectbox: ^5.3.1
61 objectbox_flutter_libs: ^5.3.1
62 path: ^1.9.1
62 - flutter_gemma: 1.0.0
63 + flutter_gemma: ^1.0.0
64 + flutter_gemma_litertlm: ^1.0.0
65 wakelock_plus: ^1.2.8
66 flutter_local_notifications: ^22.0.1
67 audioplayers: ^6.4.0
test/features/on_device/on_device_model_catalog_test.dart
+4 -3
@@ -27,13 +27,14 @@ void main() {
27 expect(ids.length, OnDeviceModel.curatedModels.length);
28 });
29
30 - test('uses concrete downloadable bundle urls', () {
30 + test('uses concrete downloadable LiteRT-LM bundle urls', () {
31 for (final model in OnDeviceModel.curatedModels) {
32 expect(model.huggingFaceUrl, startsWith('https://huggingface.co/'));
33 expect(
34 model.huggingFaceUrl,
35 - anyOf(endsWith('.litertlm'), endsWith('.task')),
36 - reason: '${model.id} must point to a LiteRT model bundle',
35 + endsWith('.litertlm'),
36 + reason:
37 + '${model.id} must stay compatible with flutter_gemma_litertlm',
38 );
39 expect(model.fileName, isNotEmpty);
40 expect(model.fileName, isNot(contains('/')));