1717 replace-contents : |
1818 include: ../../analysis_options.yaml
1919
20- # analyzer:
21- # plugins:
22- # - custom_lint
20+ analyzer:
21+ plugins:
22+ - custom_lint
2323
2424 linter:
2525 rules:
9696
9797 // A fake LLM that just echoes back what it receives.
9898 void sendMessage(String message, WidgetRef ref) {
99- final chatStateNotifier = ref.read(chatStateNotifierProvider .notifier);
100- final logStateNotifier = ref.read(logStateNotifierProvider .notifier);
99+ final chatStateNotifier = ref.read(chatStateProvider .notifier);
100+ final logStateNotifier = ref.read(logStateProvider .notifier);
101101
102102 chatStateNotifier.addUserMessage(message);
103103 logStateNotifier.logUserText(message);
@@ -167,18 +167,17 @@ steps:
167167
168168 import 'package:firebase_ai/firebase_ai.dart';
169169 import 'package:firebase_core/firebase_core.dart';
170- import 'package:flutter_riverpod/flutter_riverpod.dart';
171170 import 'package:riverpod_annotation/riverpod_annotation.dart';
172171
173172 import '../firebase_options.dart';
174173
175174 part 'gemini.g.dart';
176175
177- @riverpod
176+ @Riverpod(keepAlive: true)
178177 Future<FirebaseApp> firebaseApp(Ref ref) =>
179178 Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
180179
181- @riverpod
180+ @Riverpod(keepAlive: true)
182181 Future<GenerativeModel> geminiModel(Ref ref) async {
183182 await ref.watch(firebaseAppProvider.future);
184183
@@ -207,7 +206,6 @@ steps:
207206
208207 import 'package:colorist_ui/colorist_ui.dart';
209208 import 'package:firebase_ai/firebase_ai.dart';
210- import 'package:flutter_riverpod/flutter_riverpod.dart';
211209 import 'package:riverpod_annotation/riverpod_annotation.dart';
212210
213211 import '../providers/gemini.dart';
@@ -220,8 +218,8 @@ steps:
220218
221219 Future<void> sendMessage(String message) async {
222220 final chatSession = await ref.read(chatSessionProvider.future);
223- final chatStateNotifier = ref.read(chatStateNotifierProvider .notifier);
224- final logStateNotifier = ref.read(logStateNotifierProvider .notifier);
221+ final chatStateNotifier = ref.read(chatStateProvider .notifier);
222+ final logStateNotifier = ref.read(logStateProvider .notifier);
225223
226224 chatStateNotifier.addUserMessage(message);
227225 logStateNotifier.logUserText(message);
@@ -247,7 +245,7 @@ steps:
247245 }
248246 }
249247
250- @riverpod
248+ @Riverpod(keepAlive: true)
251249 GeminiChatService geminiChatService(Ref ref) => GeminiChatService(ref);
252250 - name : Run build_runner
253251 path : colorist
@@ -298,8 +296,8 @@ steps:
298296 -
299297 - // A fake LLM that just echoes back what it receives.
300298 - void sendMessage(String message, WidgetRef ref) {
301- - final chatStateNotifier = ref.read(chatStateNotifierProvider .notifier);
302- - final logStateNotifier = ref.read(logStateNotifierProvider .notifier);
299+ - final chatStateNotifier = ref.read(chatStateProvider .notifier);
300+ - final logStateNotifier = ref.read(logStateProvider .notifier);
303301 -
304302 - chatStateNotifier.addUserMessage(message);
305303 - logStateNotifier.logUserText(message);
@@ -446,29 +444,28 @@ steps:
446444 // found in the LICENSE file.
447445
448446 import 'package:flutter/services.dart';
449- import 'package:flutter_riverpod/flutter_riverpod.dart';
450447 import 'package:riverpod_annotation/riverpod_annotation.dart';
451448
452449 part 'system_prompt.g.dart';
453450
454- @riverpod
451+ @Riverpod(keepAlive: true)
455452 Future<String> systemPrompt(Ref ref) =>
456453 rootBundle.loadString('assets/system_prompt.md');
457454 - name : Patch lib/providers/gemini.dart
458455 path : colorist/lib/providers/gemini.dart
459456 patch-u : |
460- --- a /colorist/step_03/lib/providers/gemini.dart
461- +++ b /colorist/step_03/lib/providers/gemini.dart
462- @@ -10 ,6 +10 ,7 @@ import 'package:flutter_riverpod/flutter_riverpod .dart';
457+ --- b /colorist/step_03/lib/providers/gemini.dart
458+ +++ a /colorist/step_03/lib/providers/gemini.dart
459+ @@ -9 ,6 +9 ,7 @@ import 'package:firebase_core/firebase_core .dart';
463460 import 'package:riverpod_annotation/riverpod_annotation.dart';
464461
465462 import '../firebase_options.dart';
466463 +import 'system_prompt.dart';
467464
468465 part 'gemini.g.dart';
469466
470- @@ -20 ,9 +21 ,11 @@ Future<FirebaseApp> firebaseApp(Ref ref) =>
471- @riverpod
467+ @@ -19 ,9 +20 ,11 @@ Future<FirebaseApp> firebaseApp(Ref ref) =>
468+ @Riverpod(keepAlive: true)
472469 Future<GenerativeModel> geminiModel(Ref ref) async {
473470 await ref.watch(firebaseAppProvider.future);
474471 + final systemPrompt = await ref.watch(systemPromptProvider.future);
@@ -505,7 +502,6 @@ steps:
505502 // found in the LICENSE file.
506503
507504 import 'package:firebase_ai/firebase_ai.dart';
508- import 'package:flutter_riverpod/flutter_riverpod.dart';
509505 import 'package:riverpod_annotation/riverpod_annotation.dart';
510506
511507 part 'gemini_tools.g.dart';
@@ -530,22 +526,22 @@ steps:
530526 ];
531527 }
532528
533- @riverpod
529+ @Riverpod(keepAlive: true)
534530 GeminiTools geminiTools(Ref ref) => GeminiTools(ref);
535531 - name : Patch lib/providers/gemini.dart
536532 path : colorist/lib/providers/gemini.dart
537533 patch-u : |
538- --- a /colorist/step_04/lib/providers/gemini.dart
539- +++ b /colorist/step_04/lib/providers/gemini.dart
540- @@ -10 ,6 +10 ,7 @@ import 'package:flutter_riverpod/flutter_riverpod .dart';
534+ --- b /colorist/step_04/lib/providers/gemini.dart
535+ +++ a /colorist/step_04/lib/providers/gemini.dart
536+ @@ -9 ,6 +9 ,7 @@ import 'package:firebase_core/firebase_core .dart';
541537 import 'package:riverpod_annotation/riverpod_annotation.dart';
542538
543539 import '../firebase_options.dart';
544540 +import '../services/gemini_tools.dart';
545541 import 'system_prompt.dart';
546542
547543 part 'gemini.g.dart';
548- @@ -22 ,10 +23 ,12 @@ Future<FirebaseApp> firebaseApp(Ref ref) =>
544+ @@ -21 ,10 +22 ,12 @@ Future<FirebaseApp> firebaseApp(Ref ref) =>
549545 Future<GenerativeModel> geminiModel(Ref ref) async {
550546 await ref.watch(firebaseAppProvider.future);
551547 final systemPrompt = await ref.watch(systemPromptProvider.future);
@@ -634,15 +630,15 @@ steps:
634630 patch-u : |
635631 --- b/colorist/step_05/lib/services/gemini_chat_service.dart
636632 +++ a/colorist/step_05/lib/services/gemini_chat_service.dart
637- @@ -10 ,6 +10 ,7 @@ import 'package:flutter_riverpod/flutter_riverpod .dart';
633+ @@ -9 ,6 +9 ,7 @@ import 'package:firebase_ai/firebase_ai .dart';
638634 import 'package:riverpod_annotation/riverpod_annotation.dart';
639635
640636 import '../providers/gemini.dart';
641637 +import 'gemini_tools.dart';
642638
643639 part 'gemini_chat_service.g.dart';
644640
645- @@ -33 ,6 +34 ,27 @@ class GeminiChatService {
641+ @@ -32 ,6 +33 ,27 @@ class GeminiChatService {
646642 logStateNotifier.logLlmText(responseText);
647643 chatStateNotifier.appendToMessage(llmMessage.id, responseText);
648644 }
@@ -681,9 +677,9 @@ steps:
681677
682678 +import 'package:colorist_ui/colorist_ui.dart';
683679 import 'package:firebase_ai/firebase_ai.dart';
684- import 'package:flutter_riverpod/flutter_riverpod.dart';
685680 import 'package:riverpod_annotation/riverpod_annotation.dart';
686- @@ -26,6 +27,44 @@ class GeminiTools {
681+
682+ @@ -25,6 +26,44 @@ class GeminiTools {
687683 List<Tool> get tools => [
688684 Tool.functionDeclarations([setColorFuncDecl]),
689685 ];
@@ -692,7 +688,7 @@ steps:
692688 + String functionName,
693689 + Map<String, Object?> arguments,
694690 + ) {
695- + final logStateNotifier = ref.read(logStateNotifierProvider .notifier);
691+ + final logStateNotifier = ref.read(logStateProvider .notifier);
696692 + logStateNotifier.logFunctionCall(functionName, arguments);
697693 + return switch (functionName) {
698694 + 'set_color' => handleSetColor(arguments),
@@ -701,7 +697,7 @@ steps:
701697 + }
702698 +
703699 + Map<String, Object?> handleSetColor(Map<String, Object?> arguments) {
704- + final colorStateNotifier = ref.read(colorStateNotifierProvider .notifier);
700+ + final colorStateNotifier = ref.read(colorStateProvider .notifier);
705701 + final red = (arguments['red'] as num).toDouble();
706702 + final green = (arguments['green'] as num).toDouble();
707703 + final blue = (arguments['blue'] as num).toDouble();
@@ -712,13 +708,13 @@ steps:
712708 + .toLLMContextMap(),
713709 + };
714710 +
715- + final logStateNotifier = ref.read(logStateNotifierProvider .notifier);
711+ + final logStateNotifier = ref.read(logStateProvider .notifier);
716712 + logStateNotifier.logFunctionResults(functionResults);
717713 + return functionResults;
718714 + }
719715 +
720716 + Map<String, Object?> handleUnknownFunction(String functionName) {
721- + final logStateNotifier = ref.read(logStateNotifierProvider .notifier);
717+ + final logStateNotifier = ref.read(logStateProvider .notifier);
722718 + logStateNotifier.logWarning('Unsupported function call $functionName');
723719 + return {
724720 + 'success': false,
@@ -727,7 +723,7 @@ steps:
727723 + }
728724 }
729725
730- @riverpod
726+ @Riverpod(keepAlive: true)
731727 - name : Run build_runner
732728 path : colorist
733729 dart : run build_runner build --delete-conflicting-outputs
@@ -751,13 +747,35 @@ steps:
751747 patch-u : |
752748 --- b/colorist/step_06/lib/services/gemini_chat_service.dart
753749 +++ a/colorist/step_06/lib/services/gemini_chat_service.dart
754- @@ -14,46 +14,41 @@ import 'gemini_tools.dart';
750+ @@ -6,6 +6,7 @@ import 'dart:async';
751+
752+ import 'package:colorist_ui/colorist_ui.dart';
753+ import 'package:firebase_ai/firebase_ai.dart';
754+ +import 'package:flutter_riverpod/flutter_riverpod.dart';
755+ import 'package:riverpod_annotation/riverpod_annotation.dart';
756+
757+ import '../providers/gemini.dart';
758+ @@ -13,46 +14,55 @@ import 'gemini_tools.dart';
755759
756760 part 'gemini_chat_service.g.dart';
757-
758- +final conversationStateProvider = StateProvider(
759- + (ref) => ConversationState.idle,
760- +);
761+
762+ +class ConversationStateNotifier extends Notifier<ConversationState> {
763+ + @override
764+ + ConversationState build() => ConversationState.idle;
765+ +
766+ + void busy() {
767+ + state = ConversationState.busy;
768+ + }
769+ +
770+ + void idle() {
771+ + state = ConversationState.idle;
772+ + }
773+ +}
774+ +
775+ +final conversationStateProvider =
776+ + NotifierProvider<ConversationStateNotifier, ConversationState>(
777+ + ConversationStateNotifier.new,
778+ + );
761779 +
762780 class GeminiChatService {
763781 GeminiChatService(this.ref);
@@ -766,8 +784,8 @@ steps:
766784 Future<void> sendMessage(String message) async {
767785 final chatSession = await ref.read(chatSessionProvider.future);
768786 + final conversationState = ref.read(conversationStateProvider);
769- final chatStateNotifier = ref.read(chatStateNotifierProvider .notifier);
770- final logStateNotifier = ref.read(logStateNotifierProvider .notifier);
787+ final chatStateNotifier = ref.read(chatStateProvider .notifier);
788+ final logStateNotifier = ref.read(logStateProvider .notifier);
771789
772790 + if (conversationState == ConversationState.busy) {
773791 + logStateNotifier.logWarning(
@@ -780,7 +798,7 @@ steps:
780798 + final conversationStateNotifier = ref.read(
781799 + conversationStateProvider.notifier,
782800 + );
783- + conversationStateNotifier.state = ConversationState. busy;
801+ + conversationStateNotifier.busy() ;
784802 chatStateNotifier.addUserMessage(message);
785803 logStateNotifier.logUserText(message);
786804 final llmMessage = chatStateNotifier.createLlmMessage();
@@ -820,11 +838,11 @@ steps:
820838 }
821839 } catch (e, st) {
822840 logStateNotifier.logError(e, st: st);
823- @@ -64 ,6 +59,45 @@ class GeminiChatService {
841+ @@ -63 ,6 +73,44 @@ class GeminiChatService {
824842 );
825843 } finally {
826844 chatStateNotifier.finalizeMessage(llmMessage.id);
827- + conversationStateNotifier.state = ConversationState. idle;
845+ + conversationStateNotifier.idle() ;
828846 + }
829847 + }
830848 +
@@ -833,10 +851,9 @@ steps:
833851 + String llmMessageId,
834852 + ) async {
835853 + final chatSession = await ref.read(chatSessionProvider.future);
836- + final chatStateNotifier = ref.read(chatStateNotifierProvider .notifier);
837- + final logStateNotifier = ref.read(logStateNotifierProvider .notifier);
854+ + final chatStateNotifier = ref.read(chatStateProvider .notifier);
855+ + final logStateNotifier = ref.read(logStateProvider .notifier);
838856 + final blockText = block.text;
839- +
840857 + if (blockText != null) {
841858 + logStateNotifier.logLlmText(blockText);
842859 + chatStateNotifier.appendToMessage(llmMessageId, blockText);
@@ -900,6 +917,7 @@ steps:
900917 - name : Flutter clean
901918 path : step_06
902919 flutter : clean
920+
903921 - name : step_07
904922 steps :
905923 - name : Remove generated code
@@ -917,7 +935,7 @@ steps:
917935
918936 import 'package:colorist_ui/colorist_ui.dart';
919937 import 'package:firebase_ai/firebase_ai.dart';
920- @@ -22 ,6 +23 ,10 @@ class GeminiChatService {
938+ @@ -36 ,6 +37 ,10 @@ class GeminiChatService {
921939 GeminiChatService(this.ref);
922940 final Ref ref;
923941
@@ -994,5 +1012,6 @@ steps:
9941012 - name : Flutter clean
9951013 path : step_07
9961014 flutter : clean
1015+
9971016 - name : Cleanup
9981017 rmdir : colorist
0 commit comments