mirror of
https://github.com/foss42/apidash.git
synced 2025-12-03 03:17:00 +08:00
Update Dashbot
This commit is contained in:
@@ -2,11 +2,9 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:apidash/dashbot/widgets/dashbot_widget.dart';
|
||||
|
||||
// Provider to manage DashBot visibility state
|
||||
final dashBotVisibilityProvider = StateProvider<bool>((ref) => false);
|
||||
final dashBotMinimizedProvider = StateProvider<bool>((ref) => false);
|
||||
|
||||
// Function to show DashBot in a bottom sheet (old style)
|
||||
void showDashBotBottomSheet(BuildContext context) {
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
@@ -18,13 +16,11 @@ void showDashBotBottomSheet(BuildContext context) {
|
||||
);
|
||||
}
|
||||
|
||||
// Function to toggle DashBot overlay (new style)
|
||||
void toggleDashBotOverlay(WidgetRef ref) {
|
||||
ref.read(dashBotVisibilityProvider.notifier).state = true;
|
||||
ref.read(dashBotMinimizedProvider.notifier).state = false;
|
||||
}
|
||||
|
||||
// DashBot Overlay Widget
|
||||
class DashBotOverlay extends ConsumerWidget {
|
||||
const DashBotOverlay({super.key});
|
||||
|
||||
@@ -36,7 +32,7 @@ class DashBotOverlay extends ConsumerWidget {
|
||||
elevation: 8,
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
child: SizedBox(
|
||||
width: 400, // Fixed width for the DashBot
|
||||
width: 400,
|
||||
height: isMinimized ? 120 : 450,
|
||||
child: const DashBotWidget(),
|
||||
),
|
||||
@@ -44,7 +40,6 @@ class DashBotOverlay extends ConsumerWidget {
|
||||
}
|
||||
}
|
||||
|
||||
// FloatingActionButton for DashBot
|
||||
class DashBotFAB extends ConsumerWidget {
|
||||
final bool useOverlay;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import 'dart:convert';
|
||||
import '../services/dashbot_service.dart';
|
||||
import 'package:apidash/dashbot/services/dashbot_service.dart';
|
||||
import 'package:apidash/models/request_model.dart';
|
||||
|
||||
class DocumentationFeature {
|
||||
|
||||
@@ -7,7 +7,6 @@ class GeneralQueryFeature {
|
||||
GeneralQueryFeature(this._client);
|
||||
|
||||
Future<String> generateResponse(String prompt, {RequestModel? requestModel, dynamic responseModel}) async {
|
||||
// Create a more focused prompt that incorporates request/response context if available
|
||||
String enhancedPrompt = prompt;
|
||||
|
||||
if (requestModel != null && responseModel != null) {
|
||||
|
||||
@@ -22,20 +22,15 @@ class TestGeneratorFeature {
|
||||
.toUpperCase() ??
|
||||
"GET";
|
||||
final endpoint = requestModel.httpRequestModel?.url ?? "Unknown Endpoint";
|
||||
final headers = requestModel.httpRequestModel?.enabledHeadersMap ?? {};
|
||||
final parameters = requestModel.httpRequestModel?.enabledParamsMap ?? {};
|
||||
final body = requestModel.httpRequestModel?.body;
|
||||
final rawResponse = responseModel.body;
|
||||
final responseBody =
|
||||
rawResponse is String ? rawResponse : jsonEncode(rawResponse);
|
||||
final statusCode = responseModel.statusCode ?? 0;
|
||||
|
||||
// Extract base URL and endpoint path
|
||||
Uri uri = Uri.parse(endpoint);
|
||||
final baseUrl = "${uri.scheme}://${uri.host}";
|
||||
final path = uri.path;
|
||||
|
||||
// Analyze parameter types and values
|
||||
final parameterAnalysis = _analyzeParameters(uri.queryParameters);
|
||||
|
||||
final prompt = """
|
||||
@@ -67,11 +62,7 @@ For each test case:
|
||||
Focus on creating realistic test values based on the API context (e.g., for a country flag API, use real country codes, invalid codes, etc.)
|
||||
""";
|
||||
|
||||
// Generate the test cases
|
||||
final testCases = await _service.generateResponse(prompt);
|
||||
|
||||
// Return only a button trigger message with the test cases hidden
|
||||
// This will be detected in DashBotWidget to show only a button instead of the full text
|
||||
return "TEST_CASES_HIDDEN\n$testCases";
|
||||
}
|
||||
|
||||
@@ -83,7 +74,6 @@ Focus on creating realistic test values based on the API context (e.g., for a co
|
||||
Map<String, String> analysis = {};
|
||||
|
||||
parameters.forEach((key, value) {
|
||||
// Try to determine parameter type and format
|
||||
if (RegExp(r'^[A-Z]{3}$').hasMatch(value)) {
|
||||
analysis[key] = "Appears to be a 3-letter country code (ISO 3166-1 alpha-3)";
|
||||
} else if (RegExp(r'^[A-Z]{2}$').hasMatch(value)) {
|
||||
|
||||
@@ -2,7 +2,7 @@ import 'package:apidash/dashbot/features/debug.dart';
|
||||
import 'package:apidash/dashbot/features/documentation.dart';
|
||||
import 'package:ollama_dart/ollama_dart.dart';
|
||||
import 'package:apidash/dashbot/features/explain.dart';
|
||||
import 'package:apidash/dashbot/features/test_generator.dart'; // New import
|
||||
import 'package:apidash/dashbot/features/test_generator.dart';
|
||||
import 'package:apidash/models/request_model.dart';
|
||||
import 'package:apidash/dashbot/features/general_query.dart';
|
||||
|
||||
@@ -11,7 +11,7 @@ class DashBotService {
|
||||
late final ExplainFeature _explainFeature;
|
||||
late final DebugFeature _debugFeature;
|
||||
late final DocumentationFeature _documentationFeature;
|
||||
late final TestGeneratorFeature _testGeneratorFeature; // New feature
|
||||
late final TestGeneratorFeature _testGeneratorFeature;
|
||||
final GeneralQueryFeature _generalQueryFeature;
|
||||
|
||||
DashBotService()
|
||||
@@ -20,7 +20,7 @@ class DashBotService {
|
||||
_explainFeature = ExplainFeature(this);
|
||||
_debugFeature = DebugFeature(this);
|
||||
_documentationFeature = DocumentationFeature(this);
|
||||
_testGeneratorFeature = TestGeneratorFeature(this); // Initialize new feature
|
||||
_testGeneratorFeature = TestGeneratorFeature(this);
|
||||
}
|
||||
|
||||
Future<String> generateResponse(String prompt) async {
|
||||
@@ -38,7 +38,7 @@ class DashBotService {
|
||||
} else if (input == "Document API") {
|
||||
return _documentationFeature.generateApiDocumentation(
|
||||
requestModel: requestModel, responseModel: responseModel);
|
||||
} else if (input == "Test API") { // New condition
|
||||
} else if (input == "Test API") {
|
||||
return _testGeneratorFeature.generateApiTests(
|
||||
requestModel: requestModel, responseModel: responseModel);
|
||||
}
|
||||
|
||||
@@ -7,7 +7,9 @@ import 'test_runner_widget.dart';
|
||||
import 'chat_bubble.dart';
|
||||
|
||||
class DashBotWidget extends ConsumerStatefulWidget {
|
||||
const DashBotWidget({super.key});
|
||||
const DashBotWidget({
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
ConsumerState<DashBotWidget> createState() => _DashBotWidgetState();
|
||||
@@ -33,7 +35,6 @@ class _DashBotWidgetState extends ConsumerState<DashBotWidget> {
|
||||
|
||||
Future<void> _sendMessage(String message) async {
|
||||
if (message.trim().isEmpty) return;
|
||||
|
||||
final dashBotService = ref.read(dashBotServiceProvider);
|
||||
final requestModel = ref.read(selectedRequestModelProvider);
|
||||
final responseModel = requestModel?.httpResponseModel;
|
||||
@@ -48,13 +49,8 @@ class _DashBotWidgetState extends ConsumerState<DashBotWidget> {
|
||||
try {
|
||||
final response = await dashBotService.handleRequest(
|
||||
message, requestModel, responseModel);
|
||||
|
||||
// Check if this is a test case response with hidden content
|
||||
if (response.startsWith("TEST_CASES_HIDDEN\n")) {
|
||||
// Extract the test cases but don't show them in the message
|
||||
final testCases = response.replaceFirst("TEST_CASES_HIDDEN\n", "");
|
||||
|
||||
// Add a message with a marker that will trigger the button display
|
||||
ref.read(chatMessagesProvider.notifier).addMessage({
|
||||
'role': 'bot',
|
||||
'message': "Test cases generated successfully. Click the button below to run them.",
|
||||
@@ -62,7 +58,6 @@ class _DashBotWidgetState extends ConsumerState<DashBotWidget> {
|
||||
'showTestButton': true,
|
||||
});
|
||||
} else {
|
||||
// Normal message handling
|
||||
ref.read(chatMessagesProvider.notifier).addMessage({
|
||||
'role': 'bot',
|
||||
'message': response,
|
||||
@@ -135,7 +130,6 @@ class _DashBotWidgetState extends ConsumerState<DashBotWidget> {
|
||||
|
||||
Widget _buildHeader(BuildContext context) {
|
||||
final isMinimized = ref.watch(dashBotMinimizedProvider);
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.fromLTRB(16, 16, 16, 0),
|
||||
child: Row(
|
||||
@@ -147,7 +141,6 @@ class _DashBotWidgetState extends ConsumerState<DashBotWidget> {
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
// Minimize/Maximize button with proper alignment
|
||||
IconButton(
|
||||
padding: const EdgeInsets.all(8),
|
||||
visualDensity: VisualDensity.compact,
|
||||
@@ -160,7 +153,6 @@ class _DashBotWidgetState extends ConsumerState<DashBotWidget> {
|
||||
ref.read(dashBotMinimizedProvider.notifier).state = !isMinimized;
|
||||
},
|
||||
),
|
||||
// Close button
|
||||
IconButton(
|
||||
padding: const EdgeInsets.all(8),
|
||||
visualDensity: VisualDensity.compact,
|
||||
@@ -170,7 +162,6 @@ class _DashBotWidgetState extends ConsumerState<DashBotWidget> {
|
||||
ref.read(dashBotVisibilityProvider.notifier).state = false;
|
||||
},
|
||||
),
|
||||
// Clear chat button
|
||||
IconButton(
|
||||
padding: const EdgeInsets.all(8),
|
||||
visualDensity: VisualDensity.compact,
|
||||
@@ -302,7 +293,6 @@ class _DashBotWidgetState extends ConsumerState<DashBotWidget> {
|
||||
|
||||
Widget _buildInputArea(BuildContext context) {
|
||||
final isMinimized = ref.watch(dashBotMinimizedProvider);
|
||||
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import 'dart:convert';
|
||||
import 'package:apidash_core/apidash_core.dart' as http;
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'dart:convert';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'content_renderer.dart';
|
||||
|
||||
class TestRunnerWidget extends ConsumerStatefulWidget {
|
||||
|
||||
Reference in New Issue
Block a user