Integrate Continuous Mode in Chat System (#5167)

This commit is contained in:
hunteraraujo
2023-09-06 12:24:44 -07:00
committed by GitHub
6 changed files with 103 additions and 23 deletions

View File

@@ -1,10 +1,13 @@
class StepRequestBody {
final String input;
final String? input;
final Map<String, dynamic>? additionalInput;
StepRequestBody({required this.input, this.additionalInput});
Map<String, dynamic> toJson() {
if (input == null && additionalInput == null) {
return {};
}
return {'input': input, 'additional_input': additionalInput};
}
}

View File

@@ -10,6 +10,14 @@ class ChatViewModel with ChangeNotifier {
List<Chat> _chats = [];
String? _currentTaskId;
bool _isContinuousMode = false;
bool get isContinuousMode => _isContinuousMode;
set isContinuousMode(bool value) {
_isContinuousMode = value;
notifyListeners();
}
ChatViewModel(this._chatService);
/// Returns the current list of chats.
@@ -95,7 +103,7 @@ class ChatViewModel with ChangeNotifier {
}
/// Sends a chat message for a specific task.
void sendChatMessage(String message) async {
void sendChatMessage(String? message) async {
if (_currentTaskId == null) {
print("Error: Task ID is not set.");
return;
@@ -112,13 +120,17 @@ class ChatViewModel with ChangeNotifier {
Step executedStep = Step.fromMap(executedStepResponse);
// Create a Chat object for the user message
final userChat = Chat(
id: executedStep.stepId,
taskId: executedStep.taskId,
message: executedStep.input,
timestamp: DateTime.now(),
messageType: MessageType.user,
);
if (executedStep.input.isNotEmpty) {
final userChat = Chat(
id: executedStep.stepId,
taskId: executedStep.taskId,
message: executedStep.input,
timestamp: DateTime.now(),
messageType: MessageType.user,
);
_chats.add(userChat);
}
// Create a Chat object for the agent message
final agentChat = Chat(
@@ -129,13 +141,15 @@ class ChatViewModel with ChangeNotifier {
messageType: MessageType.agent,
jsonResponse: executedStepResponse);
// Add the user and agent chats to the list
_chats.add(userChat);
_chats.add(agentChat);
// Notify UI of the new chats
notifyListeners();
if (_isContinuousMode) {
sendChatMessage(null);
}
print("Chats added for task ID: $_currentTaskId");
} catch (error) {
// TODO: Bubble up errors to UI

View File

@@ -73,4 +73,11 @@ class TaskViewModel with ChangeNotifier {
throw ArgumentError(errorMessage);
}
}
/// Deselects the currently selected task.
void deselectTask() {
_selectedTask = null;
print("Deselected the current task.");
notifyListeners(); // Notify listeners to rebuild UI
}
}

View File

@@ -3,10 +3,14 @@ import 'package:flutter/material.dart';
class ChatInputField extends StatefulWidget {
// Callback to be triggered when the send button is pressed
final Function(String) onSendPressed;
final Function() onContinuousModePressed;
final bool isContinuousMode;
const ChatInputField({
Key? key,
required this.onSendPressed,
required this.onContinuousModePressed,
this.isContinuousMode = false,
}) : super(key: key);
@override
@@ -16,6 +20,23 @@ class ChatInputField extends StatefulWidget {
class _ChatInputFieldState extends State<ChatInputField> {
// Controller for the TextField to manage its content
final TextEditingController _controller = TextEditingController();
final FocusNode _focusNode = FocusNode();
@override
void initState() {
super.initState();
_focusNode.addListener(() {
if (_focusNode.hasFocus && widget.isContinuousMode) {
widget.onContinuousModePressed();
}
});
}
@override
void dispose() {
_focusNode.dispose(); // Dispose of the FocusNode when you're done.
super.dispose();
}
@override
Widget build(BuildContext context) {
@@ -51,21 +72,48 @@ class _ChatInputFieldState extends State<ChatInputField> {
reverse: true,
child: TextField(
controller: _controller,
focusNode: _focusNode,
// Allowing the TextField to expand vertically and accommodate multiple lines
maxLines: null,
decoration: InputDecoration(
hintText: 'Type a message...',
border: InputBorder.none,
suffixIcon: IconButton(
splashRadius: 0.1,
icon: const Icon(Icons.send),
onPressed: () {
// TODO: We allow empty messages?
if (_controller.text.isNotEmpty) {
widget.onSendPressed(_controller.text);
_controller.clear();
}
},
suffixIcon: Row(
mainAxisSize: MainAxisSize.min, // Set to minimum space
children: [
if (!widget.isContinuousMode)
Tooltip(
message: 'Send a single message',
child: IconButton(
splashRadius: 0.1,
icon: const Icon(Icons.send),
onPressed: () {
widget.onSendPressed(_controller.text);
_controller.clear();
},
),
),
// TODO: Include pop up to explain continuous mode reprecussions
Tooltip(
message: widget.isContinuousMode
? ''
: 'Enable continuous mode',
child: IconButton(
splashRadius: 0.1,
icon: Icon(widget.isContinuousMode
? Icons.pause
: Icons.fast_forward),
onPressed: () {
if (!widget.isContinuousMode) {
widget.onSendPressed(_controller.text);
_controller.clear();
_focusNode.unfocus();
}
widget.onContinuousModePressed();
},
),
)
],
),
),
),

View File

@@ -56,13 +56,20 @@ class _ChatViewState extends State<ChatView> {
child: ChatInputField(
onSendPressed: (message) async {
if (widget.viewModel.currentTaskId != null) {
widget.viewModel.sendChatMessage(message);
widget.viewModel
.sendChatMessage((message == "") ? null : message);
} else {
String newTaskId = await taskViewModel.createTask(message);
widget.viewModel.setCurrentTaskId(newTaskId);
widget.viewModel.sendChatMessage(message);
widget.viewModel
.sendChatMessage((message == "") ? null : message);
}
},
onContinuousModePressed: () {
widget.viewModel.isContinuousMode =
!widget.viewModel.isContinuousMode;
},
isContinuousMode: widget.viewModel.isContinuousMode,
),
),
],

View File

@@ -46,6 +46,7 @@ class _TaskViewState extends State<TaskView> {
final chatViewModel =
Provider.of<ChatViewModel>(context, listen: false);
chatViewModel.clearCurrentTaskAndChats();
widget.viewModel.deselectTask();
print(
'New Task button pressed, cleared current task ID and chats');
},