Skip to content

Commit 1da6b5f

Browse files
committed
Finish step 6
1 parent 6258e94 commit 1da6b5f

File tree

16 files changed

+261
-43
lines changed

16 files changed

+261
-43
lines changed

colorist/codelab_rebuild.yaml

Lines changed: 122 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,6 @@ steps:
196196
197197
import 'dart:async';
198198
199-
import 'package:colorist_ui/models/message.dart';
200199
import 'package:colorist_ui/providers/chat_state_notifier.dart';
201200
import 'package:colorist_ui/providers/log_state_notifier.dart';
202201
import 'package:firebase_vertexai/firebase_vertexai.dart';
@@ -218,13 +217,20 @@ steps:
218217
219218
chatStateNotifier.addUserMessage(message);
220219
logStateNotifier.logUserText(message);
220+
final llmMessage = chatStateNotifier.createLlmMessage();
221221
try {
222222
final response = await chatSession.sendMessage(Content.text(message));
223223
final responseText = response.text?.trim() ?? 'No text response received';
224224
logStateNotifier.logLlmText(responseText);
225-
chatStateNotifier.addLlmMessage(responseText, MessageState.complete);
225+
chatStateNotifier.appendToMessage(llmMessage.id, responseText);
226226
} catch (e, st) {
227227
logStateNotifier.logError(e, st: st);
228+
chatStateNotifier.appendToMessage(
229+
llmMessage.id,
230+
"\nI'm sorry, I encountered an error processing your request. Please try again.",
231+
);
232+
} finally {
233+
chatStateNotifier.finalizeMessage(llmMessage.id);
228234
}
229235
}
230236
}
@@ -654,7 +660,7 @@ steps:
654660
patch-u: |
655661
--- b/colorist/step_05/lib/services/gemini_chat_service.dart
656662
+++ a/colorist/step_05/lib/services/gemini_chat_service.dart
657-
@@ -12,6 +12,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
663+
@@ -11,6 +11,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
658664
import 'package:riverpod_annotation/riverpod_annotation.dart';
659665
660666
import '../providers/gemini.dart';
@@ -665,7 +671,7 @@ steps:
665671
@@ -31,6 +32,13 @@ class GeminiChatService {
666672
final responseText = response.text?.trim() ?? 'No text response received';
667673
logStateNotifier.logLlmText(responseText);
668-
chatStateNotifier.addLlmMessage(responseText, MessageState.complete);
674+
chatStateNotifier.appendToMessage(llmMessage.id, responseText);
669675
+
670676
+ if (response.functionCalls.isNotEmpty) {
671677
+ final geminiTools = ref.read(geminiToolsProvider);
@@ -675,7 +681,7 @@ steps:
675681
+ }
676682
} catch (e, st) {
677683
logStateNotifier.logError(e, st: st);
678-
}
684+
chatStateNotifier.appendToMessage(
679685
- name: Patch lib/services/gemini_tools.dart
680686
path: colorist/lib/services/gemini_tools.dart
681687
patch-u: |
@@ -750,7 +756,117 @@ steps:
750756
steps:
751757
- name: Remove generated code
752758
rmdir: step_06
753-
759+
- name: Patch lib/services/gemini_chat_service.dart
760+
path: colorist/lib/services/gemini_chat_service.dart
761+
patch-u: |
762+
--- b/colorist/step_06/lib/services/gemini_chat_service.dart
763+
+++ a/colorist/step_06/lib/services/gemini_chat_service.dart
764+
@@ -4,6 +4,7 @@
765+
766+
import 'dart:async';
767+
768+
+import 'package:colorist_ui/models/conversation_state.dart';
769+
import 'package:colorist_ui/providers/chat_state_notifier.dart';
770+
import 'package:colorist_ui/providers/log_state_notifier.dart';
771+
import 'package:firebase_vertexai/firebase_vertexai.dart';
772+
@@ -15,29 +16,41 @@ import 'gemini_tools.dart';
773+
774+
part 'gemini_chat_service.g.dart';
775+
776+
+final conversationStateProvider = StateProvider(
777+
+ (ref) => ConversationState.idle,
778+
+);
779+
+
780+
class GeminiChatService {
781+
GeminiChatService(this.ref);
782+
final Ref ref;
783+
784+
Future<void> sendMessage(String message) async {
785+
final chatSession = await ref.read(chatSessionProvider.future);
786+
+ final conversationState = ref.read(conversationStateProvider);
787+
final chatStateNotifier = ref.read(chatStateNotifierProvider.notifier);
788+
final logStateNotifier = ref.read(logStateNotifierProvider.notifier);
789+
790+
+ if (conversationState == ConversationState.busy) {
791+
+ logStateNotifier.logWarning(
792+
+ "Can't send a message while a conversation is in progress",
793+
+ );
794+
+ throw Exception(
795+
+ "Can't send a message while a conversation is in progress",
796+
+ );
797+
+ }
798+
+ final conversationStateNotifier = ref.read(
799+
+ conversationStateProvider.notifier,
800+
+ );
801+
+ conversationStateNotifier.state = ConversationState.busy;
802+
chatStateNotifier.addUserMessage(message);
803+
logStateNotifier.logUserText(message);
804+
final llmMessage = chatStateNotifier.createLlmMessage();
805+
try {
806+
- final response = await chatSession.sendMessage(Content.text(message));
807+
- final responseText = response.text?.trim() ?? 'No text response received';
808+
- logStateNotifier.logLlmText(responseText);
809+
- chatStateNotifier.appendToMessage(llmMessage.id, responseText);
810+
-
811+
- if (response.functionCalls.isNotEmpty) {
812+
- final geminiTools = ref.read(geminiToolsProvider);
813+
- for (final functionCall in response.functionCalls) {
814+
- geminiTools.handleFunctionCall(functionCall.name, functionCall.args);
815+
- }
816+
+ final responseStream = chatSession.sendMessageStream(
817+
+ Content.text(message),
818+
+ );
819+
+ await for (final block in responseStream) {
820+
+ _processBlock(block, llmMessage.id);
821+
}
822+
} catch (e, st) {
823+
logStateNotifier.logError(e, st: st);
824+
@@ -47,6 +60,24 @@ class GeminiChatService {
825+
);
826+
} finally {
827+
chatStateNotifier.finalizeMessage(llmMessage.id);
828+
+ conversationStateNotifier.state = ConversationState.idle;
829+
+ }
830+
+ }
831+
+
832+
+ void _processBlock(GenerateContentResponse block, String llmMessageId) {
833+
+ var blockText = block.text;
834+
+ if (blockText != null) {
835+
+ final chatStateNotifier = ref.read(chatStateNotifierProvider.notifier);
836+
+ final logStateNotifier = ref.read(logStateNotifierProvider.notifier);
837+
+ logStateNotifier.logLlmText(blockText);
838+
+ chatStateNotifier.appendToMessage(llmMessageId, blockText);
839+
+ }
840+
+
841+
+ if (block.functionCalls.isNotEmpty) {
842+
+ final geminiTools = ref.read(geminiToolsProvider);
843+
+ for (final functionCall in block.functionCalls) {
844+
+ geminiTools.handleFunctionCall(functionCall.name, functionCall.args);
845+
+ }
846+
}
847+
}
848+
}
849+
- name: Patch lib/main.dart
850+
path: colorist/lib/main.dart
851+
patch-u: |
852+
--- b/colorist/step_06/lib/main.dart
853+
+++ a/colorist/step_06/lib/main.dart
854+
@@ -33,6 +33,7 @@ class MainApp extends ConsumerWidget {
855+
@override
856+
Widget build(BuildContext context, WidgetRef ref) {
857+
final model = ref.watch(geminiModelProvider);
858+
+ final conversationState = ref.watch(conversationStateProvider);
859+
860+
return MaterialApp(
861+
theme: ThemeData(
862+
@@ -41,6 +42,7 @@ class MainApp extends ConsumerWidget {
863+
home: model.when(
864+
data:
865+
(data) => MainScreen(
866+
+ conversationState: conversationState,
867+
sendMessage: (text) {
868+
ref.read(geminiChatServiceProvider).sendMessage(text);
869+
},
754870
- name: Run build_runner
755871
path: colorist
756872
dart: run build_runner build --delete-conflicting-outputs

colorist/step_01/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ environment:
99
dependencies:
1010
flutter:
1111
sdk: flutter
12-
colorist_ui: ^0.0.1
12+
colorist_ui: ^0.0.3
1313
flutter_riverpod: ^2.6.1
1414
logging: ^1.3.0
1515
riverpod_annotation: ^2.6.1

colorist/step_02/lib/services/gemini_chat_service.dart

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
import 'dart:async';
66

7-
import 'package:colorist_ui/models/message.dart';
87
import 'package:colorist_ui/providers/chat_state_notifier.dart';
98
import 'package:colorist_ui/providers/log_state_notifier.dart';
109
import 'package:firebase_vertexai/firebase_vertexai.dart';
@@ -26,13 +25,20 @@ class GeminiChatService {
2625

2726
chatStateNotifier.addUserMessage(message);
2827
logStateNotifier.logUserText(message);
28+
final llmMessage = chatStateNotifier.createLlmMessage();
2929
try {
3030
final response = await chatSession.sendMessage(Content.text(message));
3131
final responseText = response.text?.trim() ?? 'No text response received';
3232
logStateNotifier.logLlmText(responseText);
33-
chatStateNotifier.addLlmMessage(responseText, MessageState.complete);
33+
chatStateNotifier.appendToMessage(llmMessage.id, responseText);
3434
} catch (e, st) {
3535
logStateNotifier.logError(e, st: st);
36+
chatStateNotifier.appendToMessage(
37+
llmMessage.id,
38+
"\nI'm sorry, I encountered an error processing your request. Please try again.",
39+
);
40+
} finally {
41+
chatStateNotifier.finalizeMessage(llmMessage.id);
3642
}
3743
}
3844
}

colorist/step_02/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ environment:
99
dependencies:
1010
flutter:
1111
sdk: flutter
12-
colorist_ui: ^0.0.1
12+
colorist_ui: ^0.0.3
1313
flutter_riverpod: ^2.6.1
1414
logging: ^1.3.0
1515
riverpod_annotation: ^2.6.1

colorist/step_03/lib/services/gemini_chat_service.dart

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
import 'dart:async';
66

7-
import 'package:colorist_ui/models/message.dart';
87
import 'package:colorist_ui/providers/chat_state_notifier.dart';
98
import 'package:colorist_ui/providers/log_state_notifier.dart';
109
import 'package:firebase_vertexai/firebase_vertexai.dart';
@@ -26,13 +25,20 @@ class GeminiChatService {
2625

2726
chatStateNotifier.addUserMessage(message);
2827
logStateNotifier.logUserText(message);
28+
final llmMessage = chatStateNotifier.createLlmMessage();
2929
try {
3030
final response = await chatSession.sendMessage(Content.text(message));
3131
final responseText = response.text?.trim() ?? 'No text response received';
3232
logStateNotifier.logLlmText(responseText);
33-
chatStateNotifier.addLlmMessage(responseText, MessageState.complete);
33+
chatStateNotifier.appendToMessage(llmMessage.id, responseText);
3434
} catch (e, st) {
3535
logStateNotifier.logError(e, st: st);
36+
chatStateNotifier.appendToMessage(
37+
llmMessage.id,
38+
"\nI'm sorry, I encountered an error processing your request. Please try again.",
39+
);
40+
} finally {
41+
chatStateNotifier.finalizeMessage(llmMessage.id);
3642
}
3743
}
3844
}

colorist/step_03/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ environment:
99
dependencies:
1010
flutter:
1111
sdk: flutter
12-
colorist_ui: ^0.0.1
12+
colorist_ui: ^0.0.3
1313
flutter_riverpod: ^2.6.1
1414
logging: ^1.3.0
1515
riverpod_annotation: ^2.6.1

colorist/step_04/lib/services/gemini_chat_service.dart

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
import 'dart:async';
66

7-
import 'package:colorist_ui/models/message.dart';
87
import 'package:colorist_ui/providers/chat_state_notifier.dart';
98
import 'package:colorist_ui/providers/log_state_notifier.dart';
109
import 'package:firebase_vertexai/firebase_vertexai.dart';
@@ -26,13 +25,20 @@ class GeminiChatService {
2625

2726
chatStateNotifier.addUserMessage(message);
2827
logStateNotifier.logUserText(message);
28+
final llmMessage = chatStateNotifier.createLlmMessage();
2929
try {
3030
final response = await chatSession.sendMessage(Content.text(message));
3131
final responseText = response.text?.trim() ?? 'No text response received';
3232
logStateNotifier.logLlmText(responseText);
33-
chatStateNotifier.addLlmMessage(responseText, MessageState.complete);
33+
chatStateNotifier.appendToMessage(llmMessage.id, responseText);
3434
} catch (e, st) {
3535
logStateNotifier.logError(e, st: st);
36+
chatStateNotifier.appendToMessage(
37+
llmMessage.id,
38+
"\nI'm sorry, I encountered an error processing your request. Please try again.",
39+
);
40+
} finally {
41+
chatStateNotifier.finalizeMessage(llmMessage.id);
3642
}
3743
}
3844
}

colorist/step_04/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ environment:
99
dependencies:
1010
flutter:
1111
sdk: flutter
12-
colorist_ui: ^0.0.1
12+
colorist_ui: ^0.0.3
1313
flutter_riverpod: ^2.6.1
1414
logging: ^1.3.0
1515
riverpod_annotation: ^2.6.1

colorist/step_05/lib/services/gemini_chat_service.dart

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
import 'dart:async';
66

7-
import 'package:colorist_ui/models/message.dart';
87
import 'package:colorist_ui/providers/chat_state_notifier.dart';
98
import 'package:colorist_ui/providers/log_state_notifier.dart';
109
import 'package:firebase_vertexai/firebase_vertexai.dart';
@@ -27,11 +26,12 @@ class GeminiChatService {
2726

2827
chatStateNotifier.addUserMessage(message);
2928
logStateNotifier.logUserText(message);
29+
final llmMessage = chatStateNotifier.createLlmMessage();
3030
try {
3131
final response = await chatSession.sendMessage(Content.text(message));
3232
final responseText = response.text?.trim() ?? 'No text response received';
3333
logStateNotifier.logLlmText(responseText);
34-
chatStateNotifier.addLlmMessage(responseText, MessageState.complete);
34+
chatStateNotifier.appendToMessage(llmMessage.id, responseText);
3535

3636
if (response.functionCalls.isNotEmpty) {
3737
final geminiTools = ref.read(geminiToolsProvider);
@@ -41,6 +41,12 @@ class GeminiChatService {
4141
}
4242
} catch (e, st) {
4343
logStateNotifier.logError(e, st: st);
44+
chatStateNotifier.appendToMessage(
45+
llmMessage.id,
46+
"\nI'm sorry, I encountered an error processing your request. Please try again.",
47+
);
48+
} finally {
49+
chatStateNotifier.finalizeMessage(llmMessage.id);
4450
}
4551
}
4652
}

colorist/step_05/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ environment:
99
dependencies:
1010
flutter:
1111
sdk: flutter
12-
colorist_ui: ^0.0.1
12+
colorist_ui: ^0.0.3
1313
flutter_riverpod: ^2.6.1
1414
logging: ^1.3.0
1515
riverpod_annotation: ^2.6.1

0 commit comments

Comments
 (0)