feat: tools implementation

This commit is contained in:
cogwheel0
2025-08-19 20:26:19 +05:30
parent d3742944bc
commit 267a45cd9e
8 changed files with 189 additions and 14 deletions

View File

@@ -507,20 +507,22 @@ Future<void> regenerateMessage(
Future<void> sendMessage(
WidgetRef ref,
String message,
List<String>? attachments,
) async {
List<String>? attachments, [
List<String>? toolIds,
]) async {
debugPrint(
'DEBUG: sendMessage called with message: $message, attachments: $attachments',
'DEBUG: sendMessage called with message: $message, attachments: $attachments, tools: $toolIds',
);
await _sendMessageInternal(ref, message, attachments);
await _sendMessageInternal(ref, message, attachments, toolIds);
}
// Internal send message implementation
Future<void> _sendMessageInternal(
dynamic ref,
String message,
List<String>? attachments,
) async {
List<String>? attachments, [
List<String>? toolIds,
]) async {
debugPrint('DEBUG: _sendMessageInternal called');
debugPrint('DEBUG: Message: $message');
debugPrint('DEBUG: Attachments: $attachments');
@@ -543,7 +545,7 @@ Future<void> _sendMessageInternal(
debugPrint('DEBUG: Active conversation before send: ${activeConversation?.id}');
// Create user message first
debugPrint('DEBUG: Creating user message with attachments: $attachments');
debugPrint('DEBUG: Creating user message with attachments: $attachments, tools: $toolIds');
final userMessage = ChatMessage(
id: const Uuid().v4(),
role: 'user',
@@ -794,8 +796,11 @@ Future<void> _sendMessageInternal(
// Debug log to track web search state
debugPrint('DEBUG: Web search toggle state: $webSearchEnabled');
// No need for function calling tools since we're using retrieval directly
final tools = <Map<String, dynamic>>[];
// Prepare tools list - pass tool IDs directly
final List<String>? toolIdsForApi = (toolIds != null && toolIds.isNotEmpty) ? toolIds : null;
if (toolIdsForApi != null) {
debugPrint('DEBUG: Including tool IDs: $toolIdsForApi');
}
try {
// Use the model's actual supported parameters if available
@@ -927,7 +932,7 @@ Future<void> _sendMessageInternal(
messages: conversationMessages,
model: selectedModel.id,
conversationId: activeConversation?.id,
tools: tools.isNotEmpty ? tools : null,
toolIds: toolIdsForApi,
enableWebSearch: webSearchEnabled,
modelItem: modelItem,
);

View File

@@ -22,6 +22,7 @@ import '../services/file_attachment_service.dart';
import '../../navigation/views/chats_list_page.dart';
import '../../files/views/files_page.dart';
import '../../profile/views/profile_page.dart';
import '../../tools/providers/tools_providers.dart';
import '../../../shared/widgets/offline_indicator.dart';
import '../../../core/services/connectivity_service.dart';
import '../../../core/models/chat_message.dart';
@@ -289,11 +290,16 @@ class _ChatPageState extends ConsumerState<ChatPage> {
debugPrint('DEBUG: Uploaded file IDs: $uploadedFileIds');
// Send message with file attachments using existing provider logic
// Get selected tools
final toolIds = ref.read(selectedToolIdsProvider);
debugPrint('DEBUG: Selected tool IDs: $toolIds');
// Send message with file attachments and tools using existing provider logic
await sendMessage(
ref,
text,
uploadedFileIds.isNotEmpty ? uploadedFileIds : null,
toolIds.isNotEmpty ? toolIds : null,
);
debugPrint('DEBUG: Message sent successfully');
@@ -744,8 +750,6 @@ class _ChatPageState extends ConsumerState<ChatPage> {
).push(MaterialPageRoute(builder: (context) => const FilesPage()));
}
void _navigateToProfile() {
Navigator.of(
context,

View File

@@ -8,6 +8,8 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'dart:io' show Platform;
import 'dart:async';
import '../providers/chat_providers.dart';
import '../../tools/widgets/tool_selector.dart';
import '../../tools/providers/tools_providers.dart';
import '../../../shared/utils/platform_utils.dart';
@@ -47,6 +49,7 @@ class _ModernChatInputState extends ConsumerState<ModernChatInput>
late AnimationController _pulseController;
Timer? _blurCollapseTimer;
bool _hasAutoFocusedOnce = false;
bool _showToolSelector = false;
@override
void initState() {
@@ -165,6 +168,11 @@ class _ModernChatInputState extends ConsumerState<ModernChatInput>
PlatformUtils.lightHaptic();
widget.onSendMessage(text);
_controller.clear();
setState(() {
_showToolSelector = false;
});
// Clear selected tools after sending
ref.read(selectedToolIdsProvider.notifier).state = [];
// Keep input expanded and focused for better UX - don't dismiss keyboard
// KeyboardUtils.dismissKeyboard(context);
// _setExpanded(false);
@@ -346,6 +354,14 @@ class _ModernChatInputState extends ConsumerState<ModernChatInput>
// Expanded bottom row with additional options
if (_isExpanded) ...[
// Tool selector
if (_showToolSelector)
const Padding(
padding: EdgeInsets.symmetric(
horizontal: Spacing.inputPadding,
),
child: ToolSelector(),
),
Container(
padding: const EdgeInsets.only(
left: Spacing.inputPadding,
@@ -364,6 +380,20 @@ class _ModernChatInputState extends ConsumerState<ModernChatInput>
tooltip: 'Add attachment',
),
const SizedBox(width: Spacing.sm),
// Tools button
_buildRoundButton(
icon: Icons.build,
onTap: widget.enabled
? () {
setState(() {
_showToolSelector = !_showToolSelector;
});
}
: null,
tooltip: 'Tools',
isActive: _showToolSelector || ref.watch(selectedToolIdsProvider).isNotEmpty,
),
const SizedBox(width: Spacing.sm),
Flexible(
child: Center(child: _buildResearchToggle()),
),