mirror of
https://github.com/foss42/apidash.git
synced 2025-07-02 05:57:55 +08:00
Dashbot History saving and an option to clear
This commit is contained in:
38
lib/providers/dashbot_messages.dart
Normal file
38
lib/providers/dashbot_messages.dart
Normal file
@ -0,0 +1,38 @@
|
||||
import 'dart:convert';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
final chatMessagesProvider = StateNotifierProvider<ChatMessagesNotifier, List<Map<String, dynamic>>>(
|
||||
(ref) => ChatMessagesNotifier(),
|
||||
);
|
||||
|
||||
class ChatMessagesNotifier extends StateNotifier<List<Map<String, dynamic>>> {
|
||||
ChatMessagesNotifier() : super([]) {
|
||||
_loadMessages();
|
||||
}
|
||||
|
||||
static const _storageKey = 'chatMessages';
|
||||
|
||||
Future<void> _loadMessages() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final messages = prefs.getString(_storageKey);
|
||||
if (messages != null) {
|
||||
state = List<Map<String, dynamic>>.from(json.decode(messages));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _saveMessages() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setString(_storageKey, json.encode(state));
|
||||
}
|
||||
|
||||
void addMessage(Map<String, dynamic> message) {
|
||||
state = [...state, message];
|
||||
_saveMessages();
|
||||
}
|
||||
|
||||
void clearMessages() {
|
||||
state = [];
|
||||
_saveMessages();
|
||||
}
|
||||
}
|
@ -4,3 +4,5 @@ export 'history_providers.dart';
|
||||
export 'settings_providers.dart';
|
||||
export 'ui_providers.dart';
|
||||
export 'ollama_providers.dart';
|
||||
export 'dashbot_messages.dart';
|
||||
|
||||
|
@ -54,7 +54,6 @@ class ResponseDetails extends ConsumerWidget {
|
||||
.watch(selectedRequestModelProvider.select((value) => value?.message));
|
||||
final responseModel = ref.watch(selectedRequestModelProvider
|
||||
.select((value) => value?.httpResponseModel));
|
||||
|
||||
return Column(
|
||||
children: [
|
||||
ResponsePaneHeader(
|
||||
|
@ -17,10 +17,15 @@ class OllamaService {
|
||||
return response.response.toString();
|
||||
}
|
||||
|
||||
// Explain latest API request & response
|
||||
// Explain responses & identify any discrepancy
|
||||
Future<String> explainLatestApi({required dynamic requestModel, required dynamic responseModel}) async {
|
||||
if (requestModel == null || responseModel == null) {
|
||||
return "No recent API requests found";
|
||||
return "No recent API requests found.";
|
||||
}
|
||||
|
||||
// Validate critical fields
|
||||
if (requestModel.httpRequestModel?.url == null) {
|
||||
return "Error: Invalid API request (missing endpoint).";
|
||||
}
|
||||
|
||||
// Extract request details
|
||||
@ -28,43 +33,44 @@ class OllamaService {
|
||||
.toString()
|
||||
.split('.')
|
||||
.last
|
||||
.toUpperCase()
|
||||
?? "GET";
|
||||
final endpoint = requestModel.httpRequestModel?.url ?? "Unknown endpoint";
|
||||
.toUpperCase() ?? "GET";
|
||||
final endpoint = requestModel.httpRequestModel!.url!;
|
||||
final headers = requestModel.httpRequestModel?.enabledHeadersMap ?? {};
|
||||
final parameters = requestModel.httpRequestModel?.enabledParamsMap ?? {};
|
||||
final body = requestModel.httpRequestModel?.body;
|
||||
|
||||
// Process response
|
||||
final rawResponse = responseModel.body;
|
||||
final responseBody = rawResponse is String;
|
||||
final responseBody = rawResponse is String ? rawResponse : jsonEncode(rawResponse);
|
||||
final statusCode = responseModel.statusCode ?? 0;
|
||||
|
||||
final prompt = '''
|
||||
Analyze this API interaction following these examples:
|
||||
Analyze this API interaction and **identify discrepancies**:
|
||||
|
||||
Current API Request:
|
||||
- Endpoint: $endpoint
|
||||
- Method: $method
|
||||
**API Request:**
|
||||
- Endpoint: `$endpoint`
|
||||
- Method: `$method`
|
||||
- Headers: ${headers.isNotEmpty ? jsonEncode(headers) : "None"}
|
||||
- Parameters: ${parameters.isNotEmpty ? jsonEncode(parameters) : "None"}
|
||||
- Body: ${body ?? "None"}
|
||||
|
||||
Current Response:
|
||||
**API Response:**
|
||||
- Status Code: $statusCode
|
||||
- Response Body: ${jsonEncode(responseBody)}
|
||||
- Body:
|
||||
\`\`\`json
|
||||
$responseBody
|
||||
\`\`\`
|
||||
|
||||
Required Analysis Format:
|
||||
1. Start with overall status assessment
|
||||
2. List validation/security issues
|
||||
3. Highlight request/response mismatches
|
||||
4. Suggest concrete improvements
|
||||
5. Use plain text formatting with clear section headers
|
||||
**Instructions:**
|
||||
1. Start with a **summary** of the API interaction.
|
||||
2. List **validation issues** (e.g., missing headers, invalid parameters).
|
||||
3. Highlight **request/response mismatches** (e.g., unexpected data types, missing fields).
|
||||
4. Suggest **concrete improvements** (e.g., fix parameters, add error handling).
|
||||
|
||||
Response Structure:
|
||||
API Request: [request details]
|
||||
Response: [response details]
|
||||
Analysis: [structured analysis]''';
|
||||
**Format:**
|
||||
- Use Markdown with headings (`##`, `###`).
|
||||
- Include bullet points for clarity.
|
||||
''';
|
||||
|
||||
return generateResponse(prompt);
|
||||
}
|
||||
|
@ -12,9 +12,10 @@ class ChatbotWidget extends ConsumerStatefulWidget {
|
||||
|
||||
class _ChatbotWidgetState extends ConsumerState<ChatbotWidget> {
|
||||
final TextEditingController _controller = TextEditingController();
|
||||
final List<Map<String, dynamic>> _messages = [];
|
||||
bool _isLoading = false;
|
||||
|
||||
List<Map<String, dynamic>> get _messages => ref.watch(chatMessagesProvider);
|
||||
|
||||
Future<void> _handleCodeGeneration() async {
|
||||
final language = await showDialog<String>(
|
||||
context: context,
|
||||
@ -56,11 +57,14 @@ class _ChatbotWidgetState extends ConsumerState<ChatbotWidget> {
|
||||
final responseModel = requestModel?.httpResponseModel;
|
||||
|
||||
setState(() {
|
||||
_messages.add({'role': 'user', 'message': message});
|
||||
_controller.clear();
|
||||
_isLoading = true;
|
||||
});
|
||||
|
||||
ref.read(chatMessagesProvider.notifier).addMessage({
|
||||
'role': 'user',
|
||||
'message': message
|
||||
});
|
||||
|
||||
try {
|
||||
String response;
|
||||
|
||||
@ -123,6 +127,18 @@ class _ChatbotWidgetState extends ConsumerState<ChatbotWidget> {
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const Text('DashBot', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.delete_sweep),
|
||||
tooltip: 'Clear Chat History',
|
||||
onPressed: () => ref.read(chatMessagesProvider.notifier).clearMessages(),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Wrap(
|
||||
spacing: 8,
|
||||
runSpacing: 8,
|
||||
@ -224,6 +240,21 @@ class ChatBubble extends StatelessWidget {
|
||||
child: MarkdownBody(
|
||||
data: message,
|
||||
selectable: true,
|
||||
styleSheet: MarkdownStyleSheet(
|
||||
h2: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Theme.of(context).colorScheme.onSurface,
|
||||
),
|
||||
h3: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Theme.of(context).colorScheme.onSurface,
|
||||
),
|
||||
listBullet: TextStyle(
|
||||
color: Theme.of(context).colorScheme.onSurface,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
Reference in New Issue
Block a user