Skip to content

Commit e9d1f00

Browse files
feat(flutter): trim generated output and cleanup SDK
1 parent b2de7a3 commit e9d1f00

93 files changed

Lines changed: 407 additions & 14404 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

docs/BUILD_ORGANIZATION.md

Lines changed: 0 additions & 116 deletions
This file was deleted.

docs/CPP_PROTO_OWNERSHIP.md

Lines changed: 0 additions & 530 deletions
This file was deleted.

examples/flutter/RunAnywhereAI/CLAUDE.md

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -80,15 +80,13 @@ App startup runs a multi-phase sequence in `initState` via `addPostFrameCallback
8080
1. **Eager .so loading** (Android only) — `DynamicLibrary.open()` on 6 `.so` files to preload before any SDK call
8181
2. **SDK init** — reads API key / base URL from secure storage (`KeychainHelper`); calls `RunAnywhere.initialize(...)` with or without credentials
8282
3. **Module registration** — guarded by a static `_modulesRegistered` flag to survive hot-reload. Registers: LlamaCpp (9 GGUF models), Genie NPU (Android/Snapdragon only, chip-conditional models), VLM (SmolVLM 500M), Sherpa STT/TTS (Whisper + Piper models), RAG embeddings (MiniLM), ONNX backend, RAG backend
83-
4. **Model refresh**`ModelManager.shared.refresh()` notifies all listeners
8483

8584
### State Management
8685

87-
Three patterns coexist:
86+
Two patterns coexist:
8887

89-
1. **Provider** (app-wide) — only `ModelManager.shared` is in the `MultiProvider` tree at the root
90-
2. **Singleton ChangeNotifier + ListenableBuilder** (feature-level) — `ModelListViewModel.shared`, `ToolSettingsViewModel.shared`, `ConversationStore.shared`, `DeviceInfoService.shared` are accessed directly, not through Provider
91-
3. **Local setState** (per-screen ephemeral state) — recording flags, streaming text buffers, error messages
88+
1. **Singleton ChangeNotifier + ListenableBuilder** (feature-level) — `ModelListViewModel.shared`, `ToolSettingsViewModel.shared`, `ConversationStore.shared`, `DeviceInfoService.shared` are accessed directly
89+
2. **Local setState** (per-screen UI state) — recording flags, streaming text buffers, error messages, voice setup state
9290

9391
### Navigation
9492

@@ -135,6 +133,7 @@ All AI calls go through `RunAnywhere`:
135133
- **RAG**: `DocumentService` uses `syncfusion_flutter_pdf` for PDF text extraction. The RAG model selection flow does NOT pre-load models into memory — it only passes paths to `RAGConfiguration`.
136134
- **Tools**: three demo tools registered (`get_weather`, `calculate`, `get_current_time`). Weather tool uses Open-Meteo free API via `package:http`.
137135
- **Structured Output**: uses `LLMGenerationOptions(jsonSchema:)` with predefined schemas.
136+
- **Remaining SDK-owned cleanup**: the large model catalog still lives in app startup because moving it safely requires shared SDK/package ownership beyond this example-app lane.
138137

139138
## Build Configuration Gotchas
140139

examples/flutter/RunAnywhereAI/README.md

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ This sample app demonstrates the full power of the RunAnywhere Flutter SDK:
118118
| **Speech-to-Text** | Voice transcription with batch & live modes | `RunAnywhere.stt.transcribe()` |
119119
| **Text-to-Speech** | Neural voice synthesis with Piper TTS | `RunAnywhere.tts.synthesize()` |
120120
| **Voice Assistant** | Full STT to LLM to TTS pipeline with auto-detection | `RunAnywhere.voice` |
121-
| **Model Management** | Download, load, and manage multiple AI models | `ModelManager` |
121+
| **Model Management** | Download, load, and manage multiple AI models | `RunAnywhere.models` / `RunAnywhere.downloads` |
122122
| **Storage Management** | View storage usage and delete models | `RunAnywhere.downloads.getStorageInfo()` |
123123
| **Offline Support** | All features work without internet | On-device inference |
124124

@@ -138,8 +138,8 @@ The app follows Flutter best practices with a clean architecture pattern:
138138
├───────┼────────────┼────────────┼────────────┼─────────────┼────────┤
139139
│ ▼ ▼ ▼ ▼ ▼ │
140140
│ ┌──────────────────────────────────────────────────────────────┐ │
141-
│ │ Provider State Management │ │
142-
│ │ (ModelManager, Services) │ │
141+
│ │ Feature ViewModels + UI State │ │
142+
│ │ (SDK facades, Services, ListenableBuilder) │ │
143143
│ └──────────────────────────────────────────────────────────────┘ │
144144
├─────────────────────────────────────────────────────────────────────┤
145145
│ │
@@ -161,9 +161,9 @@ The app follows Flutter best practices with a clean architecture pattern:
161161

162162
### Key Architecture Decisions
163163

164-
- **Provider Pattern**`ChangeNotifier` + `Provider` for state management
164+
- **Feature-Local State**Screens keep ephemeral UI state local and call SDK facades directly
165165
- **Feature-First Structure** — Each feature is self-contained with its own views and logic
166-
- **Shared Core Services**`ModelManager`, `AudioRecordingService`, `AudioPlayerService`
166+
- **Shared Core Services**`AudioRecordingService`, `AudioPlayerService`, persistence and device helpers
167167
- **Design System** — Consistent `AppColors`, `AppTypography`, `AppSpacing` tokens
168168
- **SDK Integration** — Direct SDK calls with async/await and Stream support
169169

@@ -190,7 +190,6 @@ RunAnywhereAI/
190190
│ │ │ └── app_types.dart # Shared type definitions
191191
│ │ │
192192
│ │ ├── services/
193-
│ │ │ ├── model_manager.dart # SDK model management wrapper
194193
│ │ │ ├── audio_recording_service.dart # Microphone capture
195194
│ │ │ ├── audio_player_service.dart # TTS playback
196195
│ │ │ ├── permission_service.dart # Permission handling

examples/flutter/RunAnywhereAI/lib/app/runanywhere_ai_app.dart

Lines changed: 35 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,16 @@ import 'dart:async';
22
import 'dart:io' show Platform;
33

44
import 'package:flutter/material.dart';
5-
import 'package:provider/provider.dart';
65
import 'package:runanywhere/runanywhere.dart';
76
import 'package:runanywhere_ai/app/content_view.dart';
87
import 'package:runanywhere_ai/core/design_system/app_colors.dart';
9-
import 'package:runanywhere_ai/core/services/model_manager.dart';
108
import 'package:runanywhere_ai/core/utilities/constants.dart';
119
import 'package:runanywhere_ai/core/utilities/keychain_helper.dart';
1210
import 'package:runanywhere_genie/runanywhere_genie.dart';
1311
import 'package:runanywhere_llamacpp/runanywhere_llamacpp.dart';
1412
import 'package:runanywhere_onnx/runanywhere_onnx.dart';
1513

16-
/// RunAnywhereAIApp (mirroring iOS RunAnywhereAIApp.swift)
14+
/// RunAnywhereAIApp
1715
///
1816
/// Main application entry point with SDK initialization.
1917
class RunAnywhereAIApp extends StatefulWidget {
@@ -87,8 +85,6 @@ class _RunAnywhereAIAppState extends State<RunAnywhereAIApp> {
8785
debugPrint(
8886
'🔧 Environment: ${RunAnywhere.environment?.description ?? "Unknown"}');
8987

90-
await ModelManager.shared.refresh();
91-
9288
debugPrint(
9389
'💡 Models registered, user can now download and select models');
9490
} catch (e) {
@@ -123,8 +119,7 @@ class _RunAnywhereAIAppState extends State<RunAnywhereAIApp> {
123119
// ── Step 1: Download ─────────────────────────────────────────
124120
debugPrint('▶ Step 1: downloading $testModelId …');
125121
final sw = Stopwatch()..start();
126-
final progressStream =
127-
RunAnywhere.downloads.start(testModelId);
122+
final progressStream = RunAnywhere.downloads.start(testModelId);
128123

129124
double lastPct = 0;
130125
await for (final p in progressStream) {
@@ -144,8 +139,6 @@ class _RunAnywhereAIAppState extends State<RunAnywhereAIApp> {
144139

145140
// Let the download adapter finalize (path update, registry sync)
146141
await Future<void>.delayed(const Duration(milliseconds: 500));
147-
await ModelManager.shared.refresh();
148-
149142
// Re-run discovery so the SDK sees the downloaded file
150143
final models = await RunAnywhere.models.available();
151144
final dlModel = models.where((m) => m.id == testModelId).firstOrNull;
@@ -170,8 +163,7 @@ class _RunAnywhereAIAppState extends State<RunAnywhereAIApp> {
170163
temperature: 0.7,
171164
systemPrompt: 'You are a helpful assistant.',
172165
);
173-
final result =
174-
await RunAnywhere.llm.generate('Hello!', genOpts);
166+
final result = await RunAnywhere.llm.generate('Hello!', genOpts);
175167
sw.stop();
176168
debugPrint(
177169
'✅ generate() => "${result.text.substring(0, result.text.length.clamp(0, 120))}"');
@@ -188,8 +180,7 @@ class _RunAnywhereAIAppState extends State<RunAnywhereAIApp> {
188180
temperature: 0.7,
189181
systemPrompt: 'You are a helpful assistant.',
190182
);
191-
final stream = RunAnywhere.llm
192-
.generateStream('What is 2+2?', streamOpts);
183+
final stream = RunAnywhere.llm.generateStream('What is 2+2?', streamOpts);
193184
final buf = StringBuffer();
194185
int tokenCount = 0;
195186
await for (final event in stream) {
@@ -222,7 +213,7 @@ class _RunAnywhereAIAppState extends State<RunAnywhereAIApp> {
222213
}
223214
}
224215

225-
/// True once we've registered modules + models exactly once. Without
216+
/// True once we've registered modules + models once. Without
226217
/// this guard, hot-reload (or any second call) re-runs the entire
227218
/// LLM catalog registration block, which is wasteful (B-FL-3-002).
228219
static bool _modulesRegistered = false;
@@ -248,7 +239,6 @@ class _RunAnywhereAIAppState extends State<RunAnywhereAIApp> {
248239

249240
/// Register modules with their associated models
250241
/// Each module explicitly owns its models - the framework is determined by the module
251-
/// Matches iOS registerModulesAndModels pattern exactly
252242
Future<void> _registerModulesAndModels() async {
253243
if (_modulesRegistered) {
254244
debugPrint('📦 Modules already registered — skipping (B-FL-3-002)');
@@ -505,7 +495,8 @@ class _RunAnywhereAIAppState extends State<RunAnywhereAIApp> {
505495
modality: ModelCategory.MODEL_CATEGORY_VOICE_ACTIVITY_DETECTION,
506496
memoryRequirement: 5000000,
507497
);
508-
debugPrint('✅ STT/TTS/VAD models registered via Core SDK (incl. system-tts)');
498+
debugPrint(
499+
'✅ STT/TTS/VAD models registered via Core SDK (incl. system-tts)');
509500
await Future<void>.delayed(Duration.zero);
510501

511502
// --- RAG EMBEDDINGS ---
@@ -555,42 +546,37 @@ class _RunAnywhereAIAppState extends State<RunAnywhereAIApp> {
555546

556547
@override
557548
Widget build(BuildContext context) {
558-
return MultiProvider(
559-
providers: [
560-
ChangeNotifierProvider.value(value: ModelManager.shared),
561-
],
562-
child: MaterialApp(
563-
scaffoldMessengerKey: _messengerKey,
564-
title: 'RunAnywhere AI',
565-
debugShowCheckedModeBanner: false,
566-
theme: ThemeData(
567-
colorScheme: ColorScheme.fromSeed(
568-
seedColor: AppColors.primaryBlue,
569-
brightness: Brightness.light,
570-
),
571-
useMaterial3: true,
572-
appBarTheme: const AppBarTheme(
573-
centerTitle: true,
574-
elevation: 0,
575-
),
576-
navigationBarTheme: NavigationBarThemeData(
577-
indicatorColor: AppColors.primaryBlue.withValues(alpha: 0.2),
578-
),
549+
return MaterialApp(
550+
scaffoldMessengerKey: _messengerKey,
551+
title: 'RunAnywhere AI',
552+
debugShowCheckedModeBanner: false,
553+
theme: ThemeData(
554+
colorScheme: ColorScheme.fromSeed(
555+
seedColor: AppColors.primaryBlue,
556+
brightness: Brightness.light,
557+
),
558+
useMaterial3: true,
559+
appBarTheme: const AppBarTheme(
560+
centerTitle: true,
561+
elevation: 0,
562+
),
563+
navigationBarTheme: NavigationBarThemeData(
564+
indicatorColor: AppColors.primaryBlue.withValues(alpha: 0.2),
565+
),
566+
),
567+
darkTheme: ThemeData(
568+
colorScheme: ColorScheme.fromSeed(
569+
seedColor: AppColors.primaryBlue,
570+
brightness: Brightness.dark,
579571
),
580-
darkTheme: ThemeData(
581-
colorScheme: ColorScheme.fromSeed(
582-
seedColor: AppColors.primaryBlue,
583-
brightness: Brightness.dark,
584-
),
585-
useMaterial3: true,
586-
appBarTheme: const AppBarTheme(
587-
centerTitle: true,
588-
elevation: 0,
589-
),
572+
useMaterial3: true,
573+
appBarTheme: const AppBarTheme(
574+
centerTitle: true,
575+
elevation: 0,
590576
),
591-
themeMode: ThemeMode.system,
592-
home: _buildHome(),
593577
),
578+
themeMode: ThemeMode.system,
579+
home: _buildHome(),
594580
);
595581
}
596582

0 commit comments

Comments
 (0)