mirror of
https://github.com/foss42/apidash.git
synced 2025-07-04 07:18:11 +08:00
Merge pull request #608 from siddu015/main
Add ChatBot for API Assistance
This commit is contained in:
1
lib/dashbot/dashbot.dart
Normal file
1
lib/dashbot/dashbot.dart
Normal file
@ -0,0 +1 @@
|
||||
export 'widgets/dashbot_widget.dart';
|
63
lib/dashbot/features/debug.dart
Normal file
63
lib/dashbot/features/debug.dart
Normal file
@ -0,0 +1,63 @@
|
||||
import 'dart:convert';
|
||||
import '../services/dashbot_service.dart';
|
||||
import 'package:apidash/models/request_model.dart';
|
||||
|
||||
class DebugFeature {
|
||||
final DashBotService _service;
|
||||
|
||||
DebugFeature(this._service);
|
||||
|
||||
Future<String> debugApi({
|
||||
required RequestModel? requestModel,
|
||||
required dynamic responseModel,
|
||||
}) async {
|
||||
if (requestModel == null || responseModel == null) {
|
||||
return "No recent API requests found.";
|
||||
}
|
||||
|
||||
final method = requestModel.httpRequestModel?.method
|
||||
.toString()
|
||||
.split('.')
|
||||
.last
|
||||
.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;
|
||||
|
||||
final prompt = '''
|
||||
URGENT API DEBUG ANALYSIS
|
||||
|
||||
**Request Overview:**
|
||||
- Endpoint: $endpoint
|
||||
- Method: $method
|
||||
- Status Code: $statusCode
|
||||
|
||||
**Debugging Instructions:**
|
||||
Provide a PRECISE, TEXT-ONLY explanation that:
|
||||
1. Identifies the EXACT problem
|
||||
2. Explains WHY the request failed
|
||||
3. Describes SPECIFIC steps to resolve the issue
|
||||
4. NO CODE SNIPPETS ALLOWED
|
||||
|
||||
**Request Details:**
|
||||
- Headers: ${headers.isNotEmpty ? jsonEncode(headers) : "No headers"}
|
||||
- Parameters: ${parameters.isNotEmpty ? jsonEncode(parameters) : "No parameters"}
|
||||
- Request Body: ${body ?? "Empty body"}
|
||||
|
||||
**Response Context:**
|
||||
\`\`\`
|
||||
$responseBody
|
||||
\`\`\`
|
||||
|
||||
Provide a CLEAR, ACTIONABLE solution in the SIMPLEST possible language.
|
||||
''';
|
||||
|
||||
return _service.generateResponse(prompt);
|
||||
}
|
||||
}
|
68
lib/dashbot/features/explain.dart
Normal file
68
lib/dashbot/features/explain.dart
Normal file
@ -0,0 +1,68 @@
|
||||
import 'dart:convert';
|
||||
import '../services/dashbot_service.dart';
|
||||
import 'package:apidash/models/request_model.dart';
|
||||
|
||||
class ExplainFeature {
|
||||
final DashBotService _service;
|
||||
|
||||
ExplainFeature(this._service);
|
||||
|
||||
Future<String> explainLatestApi({
|
||||
required RequestModel? requestModel,
|
||||
required dynamic responseModel,
|
||||
}) async {
|
||||
if (requestModel == null || responseModel == null) {
|
||||
return "No recent API requests found.";
|
||||
}
|
||||
|
||||
if (requestModel.httpRequestModel?.url == null) {
|
||||
return "Error: Invalid API request (missing endpoint).";
|
||||
}
|
||||
|
||||
final method = requestModel.httpRequestModel?.method
|
||||
.toString()
|
||||
.split('.')
|
||||
.last
|
||||
.toUpperCase() ??
|
||||
"GET";
|
||||
final endpoint = requestModel.httpRequestModel!.url!;
|
||||
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;
|
||||
|
||||
final prompt = '''
|
||||
FOCUSED API INTERACTION BREAKDOWN
|
||||
|
||||
**Essential Request Details:**
|
||||
- Endpoint Purpose: What is this API endpoint designed to do?
|
||||
- Interaction Type: Describe the core purpose of this specific request
|
||||
|
||||
**Request Mechanics:**
|
||||
- Exact Endpoint: $endpoint
|
||||
- HTTP Method: $method
|
||||
- Key Parameters: ${parameters.isNotEmpty ? 'Specific inputs driving the request' : 'No custom parameters'}
|
||||
|
||||
**Response CORE Insights:**
|
||||
- Status: Success or Failure?
|
||||
- Key Data Extracted: What CRITICAL information does the response contain?
|
||||
|
||||
**Precise Analysis Requirements:**
|
||||
1. Explain the API's PRIMARY function in ONE clear sentence
|
||||
2. Identify the MOST IMPORTANT piece of information returned
|
||||
3. Describe the PRACTICAL significance of this API call
|
||||
|
||||
AVOID:
|
||||
- Technical jargon
|
||||
- Unnecessary details
|
||||
- Verbose explanations
|
||||
|
||||
Deliver a CRYSTAL CLEAR, CONCISE explanation that anyone can understand.
|
||||
''';
|
||||
|
||||
return _service.generateResponse(prompt);
|
||||
}
|
||||
}
|
44
lib/dashbot/providers/dashbot_providers.dart
Normal file
44
lib/dashbot/providers/dashbot_providers.dart
Normal file
@ -0,0 +1,44 @@
|
||||
import 'dart:convert';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import '../services/dashbot_service.dart';
|
||||
|
||||
final chatMessagesProvider =
|
||||
StateNotifierProvider<ChatMessagesNotifier, List<Map<String, dynamic>>>(
|
||||
(ref) => ChatMessagesNotifier(),
|
||||
);
|
||||
|
||||
final dashBotServiceProvider = Provider<DashBotService>((ref) {
|
||||
return DashBotService();
|
||||
});
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
36
lib/dashbot/services/dashbot_service.dart
Normal file
36
lib/dashbot/services/dashbot_service.dart
Normal file
@ -0,0 +1,36 @@
|
||||
import 'package:apidash/dashbot/features/debug.dart';
|
||||
import 'package:ollama_dart/ollama_dart.dart';
|
||||
import '../features/explain.dart';
|
||||
import 'package:apidash/models/request_model.dart';
|
||||
|
||||
class DashBotService {
|
||||
final OllamaClient _client;
|
||||
late final ExplainFeature _explainFeature;
|
||||
late final DebugFeature _debugFeature;
|
||||
|
||||
DashBotService()
|
||||
: _client = OllamaClient(baseUrl: 'http://127.0.0.1:11434/api') {
|
||||
_explainFeature = ExplainFeature(this);
|
||||
_debugFeature = DebugFeature(this);
|
||||
}
|
||||
|
||||
Future<String> generateResponse(String prompt) async {
|
||||
final response = await _client.generateCompletion(
|
||||
request: GenerateCompletionRequest(model: 'llama3.2:3b', prompt: prompt),
|
||||
);
|
||||
return response.response.toString();
|
||||
}
|
||||
|
||||
Future<String> handleRequest(
|
||||
String input, RequestModel? requestModel, dynamic responseModel) async {
|
||||
if (input == "Explain API") {
|
||||
return _explainFeature.explainLatestApi(
|
||||
requestModel: requestModel, responseModel: responseModel);
|
||||
} else if (input == "Debug API") {
|
||||
return _debugFeature.debugApi(
|
||||
requestModel: requestModel, responseModel: responseModel);
|
||||
}
|
||||
|
||||
return generateResponse(input);
|
||||
}
|
||||
}
|
50
lib/dashbot/widgets/chat_bubble.dart
Normal file
50
lib/dashbot/widgets/chat_bubble.dart
Normal file
@ -0,0 +1,50 @@
|
||||
// lib/dashbot/widgets/chat_bubble.dart
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'content_renderer.dart';
|
||||
|
||||
class ChatBubble extends StatelessWidget {
|
||||
final String message;
|
||||
final bool isUser;
|
||||
|
||||
const ChatBubble({super.key, required this.message, this.isUser = false});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Align(
|
||||
alignment: isUser ? Alignment.centerRight : Alignment.centerLeft,
|
||||
child: Container(
|
||||
margin: const EdgeInsets.symmetric(vertical: 4, horizontal: 12),
|
||||
padding: const EdgeInsets.all(12),
|
||||
decoration: BoxDecoration(
|
||||
color: isUser
|
||||
? Theme.of(context).colorScheme.primaryContainer
|
||||
: Theme.of(context).colorScheme.surfaceContainerHighest,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Flexible(
|
||||
child: renderContent(context, message),
|
||||
),
|
||||
if (!isUser) ...[
|
||||
const SizedBox(width: 8),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.copy, size: 20),
|
||||
tooltip: 'Copy Response',
|
||||
onPressed: () {
|
||||
Clipboard.setData(ClipboardData(text: message));
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(content: Text('Copied to clipboard')),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
100
lib/dashbot/widgets/content_renderer.dart
Normal file
100
lib/dashbot/widgets/content_renderer.dart
Normal file
@ -0,0 +1,100 @@
|
||||
// lib/dashbot/widgets/content_renderer.dart
|
||||
import 'dart:convert';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_highlighter/flutter_highlighter.dart';
|
||||
import 'package:flutter_highlighter/themes/monokai-sublime.dart';
|
||||
import 'package:flutter_markdown/flutter_markdown.dart';
|
||||
|
||||
Widget renderContent(BuildContext context, String text) {
|
||||
if (text.isEmpty) {
|
||||
return const Text("No content to display.");
|
||||
}
|
||||
|
||||
final codeBlockPattern = RegExp(r'```(\w+)?\n([\s\S]*?)```', multiLine: true);
|
||||
final matches = codeBlockPattern.allMatches(text);
|
||||
|
||||
if (matches.isEmpty) {
|
||||
return _renderMarkdown(context, text);
|
||||
}
|
||||
|
||||
List<Widget> children = [];
|
||||
int lastEnd = 0;
|
||||
|
||||
for (var match in matches) {
|
||||
if (match.start > lastEnd) {
|
||||
children
|
||||
.add(_renderMarkdown(context, text.substring(lastEnd, match.start)));
|
||||
}
|
||||
|
||||
final language = match.group(1) ?? 'text';
|
||||
final code = match.group(2)!.trim();
|
||||
children.add(_renderCodeBlock(context, language, code));
|
||||
|
||||
lastEnd = match.end;
|
||||
}
|
||||
|
||||
if (lastEnd < text.length) {
|
||||
children.add(_renderMarkdown(context, text.substring(lastEnd)));
|
||||
}
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: children,
|
||||
);
|
||||
}
|
||||
|
||||
Widget _renderMarkdown(BuildContext context, String markdown) {
|
||||
return MarkdownBody(
|
||||
data: markdown,
|
||||
selectable: true,
|
||||
styleSheet: MarkdownStyleSheet(
|
||||
p: TextStyle(color: Theme.of(context).colorScheme.onSurface),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _renderCodeBlock(BuildContext context, String language, String code) {
|
||||
if (language == 'json') {
|
||||
try {
|
||||
final prettyJson =
|
||||
const JsonEncoder.withIndent(' ').convert(jsonDecode(code));
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(8),
|
||||
color: Theme.of(context).colorScheme.surfaceContainerLow,
|
||||
child: SelectableText(
|
||||
prettyJson,
|
||||
style: const TextStyle(fontFamily: 'monospace', fontSize: 12),
|
||||
),
|
||||
);
|
||||
} catch (e) {
|
||||
return _renderFallbackCode(context, code);
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(8),
|
||||
color: Theme.of(context).colorScheme.surfaceContainerLow,
|
||||
child: HighlightView(
|
||||
code,
|
||||
language: language,
|
||||
theme: monokaiSublimeTheme,
|
||||
textStyle: const TextStyle(fontFamily: 'monospace', fontSize: 12),
|
||||
),
|
||||
);
|
||||
} catch (e) {
|
||||
return _renderFallbackCode(context, code);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Widget _renderFallbackCode(BuildContext context, String code) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(8),
|
||||
color: Theme.of(context).colorScheme.surfaceContainerLow,
|
||||
child: SelectableText(
|
||||
code,
|
||||
style: const TextStyle(
|
||||
fontFamily: 'monospace', fontSize: 12, color: Colors.red),
|
||||
),
|
||||
);
|
||||
}
|
198
lib/dashbot/widgets/dashbot_widget.dart
Normal file
198
lib/dashbot/widgets/dashbot_widget.dart
Normal file
@ -0,0 +1,198 @@
|
||||
// lib/dashbot/widgets/dashbot_widget.dart
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:apidash/dashbot/providers/dashbot_providers.dart';
|
||||
import 'package:apidash/providers/providers.dart';
|
||||
import 'chat_bubble.dart';
|
||||
|
||||
class DashBotWidget extends ConsumerStatefulWidget {
|
||||
const DashBotWidget({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_DashBotWidgetState createState() => _DashBotWidgetState();
|
||||
}
|
||||
|
||||
class _DashBotWidgetState extends ConsumerState<DashBotWidget> {
|
||||
final TextEditingController _controller = TextEditingController();
|
||||
late ScrollController _scrollController;
|
||||
bool _isLoading = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_scrollController = ScrollController();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_scrollController.dispose();
|
||||
_controller.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
setState(() => _isLoading = true);
|
||||
|
||||
ref.read(chatMessagesProvider.notifier).addMessage({
|
||||
'role': 'user',
|
||||
'message': message,
|
||||
});
|
||||
|
||||
try {
|
||||
final response = await dashBotService.handleRequest(
|
||||
message, requestModel, responseModel);
|
||||
ref.read(chatMessagesProvider.notifier).addMessage({
|
||||
'role': 'bot',
|
||||
'message': response,
|
||||
});
|
||||
} catch (error, stackTrace) {
|
||||
print('Error in _sendMessage: $error');
|
||||
print('StackTrace: $stackTrace');
|
||||
ref.read(chatMessagesProvider.notifier).addMessage({
|
||||
'role': 'bot',
|
||||
'message': "Error: ${error.toString()}",
|
||||
});
|
||||
} finally {
|
||||
setState(() => _isLoading = false);
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
_scrollController.animateTo(
|
||||
0,
|
||||
duration: const Duration(milliseconds: 300),
|
||||
curve: Curves.easeOut,
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final messages = ref.watch(chatMessagesProvider);
|
||||
final requestModel = ref.read(selectedRequestModelProvider);
|
||||
final statusCode = requestModel?.httpResponseModel?.statusCode;
|
||||
final showDebugButton = statusCode != null && statusCode >= 400;
|
||||
|
||||
return Container(
|
||||
height: 450,
|
||||
width: double.infinity,
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.surface,
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
boxShadow: const [
|
||||
BoxShadow(color: Colors.black12, blurRadius: 8, offset: Offset(0, 4))
|
||||
],
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
_buildHeader(context),
|
||||
const SizedBox(height: 12),
|
||||
_buildQuickActions(showDebugButton),
|
||||
const SizedBox(height: 12),
|
||||
Expanded(child: _buildChatArea(messages)),
|
||||
if (_isLoading) _buildLoadingIndicator(),
|
||||
const SizedBox(height: 10),
|
||||
_buildInputArea(context),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildHeader(BuildContext context) {
|
||||
return 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',
|
||||
onPressed: () =>
|
||||
ref.read(chatMessagesProvider.notifier).clearMessages(),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildQuickActions(bool showDebugButton) {
|
||||
return Wrap(
|
||||
spacing: 8,
|
||||
runSpacing: 8,
|
||||
children: [
|
||||
ElevatedButton.icon(
|
||||
onPressed: () => _sendMessage("Explain API"),
|
||||
icon: const Icon(Icons.info_outline),
|
||||
label: const Text("Explain"),
|
||||
style: ElevatedButton.styleFrom(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
|
||||
),
|
||||
),
|
||||
if (showDebugButton)
|
||||
ElevatedButton.icon(
|
||||
onPressed: () => _sendMessage("Debug API"),
|
||||
icon: const Icon(Icons.bug_report_outlined),
|
||||
label: const Text("Debug"),
|
||||
style: ElevatedButton.styleFrom(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildChatArea(List<Map<String, dynamic>> messages) {
|
||||
return ListView.builder(
|
||||
controller: _scrollController,
|
||||
reverse: true,
|
||||
itemCount: messages.length,
|
||||
itemBuilder: (context, index) {
|
||||
final message = messages.reversed.toList()[index];
|
||||
return ChatBubble(
|
||||
message: message['message'],
|
||||
isUser: message['role'] == 'user',
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildLoadingIndicator() {
|
||||
return const Padding(
|
||||
padding: EdgeInsets.all(8.0),
|
||||
child: LinearProgressIndicator(),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildInputArea(BuildContext context) {
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
color: Theme.of(context).colorScheme.surfaceContainer,
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: TextField(
|
||||
controller: _controller,
|
||||
decoration: const InputDecoration(
|
||||
hintText: 'Ask DashBot...',
|
||||
border: InputBorder.none,
|
||||
),
|
||||
onSubmitted: _sendMessage,
|
||||
maxLines: 1,
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.send),
|
||||
onPressed: () => _sendMessage(_controller.text),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -4,6 +4,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:apidash/providers/providers.dart';
|
||||
import 'package:apidash/widgets/widgets.dart';
|
||||
import 'package:apidash/consts.dart';
|
||||
import 'package:apidash/dashbot/dashbot.dart';
|
||||
import 'common_widgets/common_widgets.dart';
|
||||
import 'envvar/environment_page.dart';
|
||||
import 'home_page/home_page.dart';
|
||||
@ -124,6 +125,17 @@ class Dashboard extends ConsumerWidget {
|
||||
],
|
||||
),
|
||||
),
|
||||
floatingActionButton: FloatingActionButton(
|
||||
onPressed: () => showModalBottomSheet(
|
||||
context: context,
|
||||
isScrollControlled: true,
|
||||
builder: (context) => const Padding(
|
||||
padding: EdgeInsets.all(16.0),
|
||||
child: DashBotWidget(),
|
||||
),
|
||||
),
|
||||
child: const Icon(Icons.help_outline),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -54,6 +54,7 @@ class ResponseDetails extends ConsumerWidget {
|
||||
.watch(selectedRequestModelProvider.select((value) => value?.message));
|
||||
final responseModel = ref.watch(selectedRequestModelProvider
|
||||
.select((value) => value?.httpResponseModel));
|
||||
|
||||
return Column(
|
||||
children: [
|
||||
ResponsePaneHeader(
|
||||
|
130
pubspec.lock
130
pubspec.lock
@ -51,10 +51,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: archive
|
||||
sha256: "0c64e928dcbefddecd234205422bcfc2b5e6d31be0b86fef0d0dd48d7b4c9742"
|
||||
sha256: "528579c7e4579719f04b21eeeeddfd73a18b31dabc22766893b7d1be7f49b967"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.0.4"
|
||||
version: "4.0.3"
|
||||
args:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -83,10 +83,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: barcode
|
||||
sha256: ab180ce22c6555d77d45f0178a523669db67f95856e3378259ef2ffeb43e6003
|
||||
sha256: "7b6729c37e3b7f34233e2318d866e8c48ddb46c1f7ad01ff7bb2a8de1da2b9f4"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.8"
|
||||
version: "2.2.9"
|
||||
bidi:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -123,18 +123,18 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: build_config
|
||||
sha256: bf80fcfb46a29945b423bd9aad884590fb1dc69b330a4d4700cac476af1708d1
|
||||
sha256: "4ae2de3e1e67ea270081eaee972e1bd8f027d459f249e0f1186730784c2e7e33"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.1"
|
||||
version: "1.1.2"
|
||||
build_daemon:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: build_daemon
|
||||
sha256: "79b2aef6ac2ed00046867ed354c88778c9c0f029df8a20fe10b5436826721ef9"
|
||||
sha256: "8e928697a82be082206edb0b9c99c5a4ad6bc31c9e9b8b2f291ae65cd4a25daa"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.0.2"
|
||||
version: "4.0.4"
|
||||
build_resolvers:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -171,10 +171,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: built_value
|
||||
sha256: "28a712df2576b63c6c005c465989a348604960c0958d28be5303ba9baa841ac2"
|
||||
sha256: "8b158ab94ec6913e480dc3f752418348b5ae099eb75868b5f4775f0572999c61"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "8.9.3"
|
||||
version: "8.9.4"
|
||||
characters:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -390,14 +390,30 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.2"
|
||||
fetch_api:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: fetch_api
|
||||
sha256: "97f46c25b480aad74f7cc2ad7ccba2c5c6f08d008e68f95c1077286ce243d0e6"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.0"
|
||||
fetch_client:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: fetch_client
|
||||
sha256: "9666ee14536778474072245ed5cba07db81ae8eb5de3b7bf4a2d1e2c49696092"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.2"
|
||||
ffi:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: ffi
|
||||
sha256: "16ed7b077ef01ad6170a3d0c57caa4a112a38d7a2ed5602e0aca9ca6f3d98da6"
|
||||
sha256: "289279317b4b16eb2bb7e271abccd4bf84ec9bdcbe999e278a94b804f5630418"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.3"
|
||||
version: "2.1.4"
|
||||
file:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -466,10 +482,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: file_selector_windows
|
||||
sha256: "8f5d2f6590d51ecd9179ba39c64f722edc15226cc93dcc8698466ad36a4a85a4"
|
||||
sha256: "320fcfb6f33caa90f0b58380489fc5ac05d99ee94b61aa96ec2bff0ba81d3c2b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.9.3+3"
|
||||
version: "0.9.3+4"
|
||||
fixnum:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -504,6 +520,14 @@ packages:
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_highlighter:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_highlighter
|
||||
sha256: "93173afd47a9ada53f3176371755e7ea4a1065362763976d06d6adfb4d946e10"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.1.1"
|
||||
flutter_hooks:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -675,10 +699,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: glob
|
||||
sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63"
|
||||
sha256: c3f1ee72c96f8f78935e18aa8cecced9ab132419e8625dc187e1c2408efc20de
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.2"
|
||||
version: "2.1.3"
|
||||
google_fonts:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -1065,6 +1089,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.2"
|
||||
ollama_dart:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: ollama_dart
|
||||
sha256: "4e40bc499b6fe46ba54a004d2da601c40bd73d66e3f18cf7b03225ccf3d481a6"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.2.2+1"
|
||||
package_config:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -1173,10 +1205,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: petitparser
|
||||
sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27
|
||||
sha256: "07c8f0b1913bcde1ff0d26e57ace2f3012ccbf2b204e070290dad3bb22797646"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.0.2"
|
||||
version: "6.1.0"
|
||||
platform:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -1252,10 +1284,10 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: printing
|
||||
sha256: b535d177fc6e8f8908e19b0ff5c1d4a87e3c4d0bf675e05aa2562af1b7853906
|
||||
sha256: "482cd5a5196008f984bb43ed0e47cbfdca7373490b62f3b27b3299275bf22a93"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.13.4"
|
||||
version: "5.14.2"
|
||||
process:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -1412,10 +1444,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_android
|
||||
sha256: "02a7d8a9ef346c9af715811b01fbd8e27845ad2c41148eefd31321471b41863d"
|
||||
sha256: a768fc8ede5f0c8e6150476e14f38e2417c0864ca36bb4582be8e21925a03c22
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.0"
|
||||
version: "2.4.6"
|
||||
shared_preferences_foundation:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -1444,10 +1476,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_web
|
||||
sha256: d2ca4132d3946fec2184261726b355836a82c33d7d5b67af32692aff18a4684e
|
||||
sha256: c49bd060261c9a3f0ff445892695d6212ff603ef3115edbb448509d407600019
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.2"
|
||||
version: "2.4.3"
|
||||
shared_preferences_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -1460,10 +1492,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shelf
|
||||
sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4
|
||||
sha256: e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.4.1"
|
||||
version: "1.4.2"
|
||||
shelf_gzip:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -1500,10 +1532,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shelf_web_socket
|
||||
sha256: cc36c297b52866d203dbf9332263c94becc2fe0ceaa9681d07b6ef9807023b67
|
||||
sha256: "3632775c8e90d6c9712f883e633716432a27758216dfb61bd86a8321c0580925"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.1"
|
||||
version: "3.0.0"
|
||||
shlex:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -1745,18 +1777,18 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_web
|
||||
sha256: "772638d3b34c779ede05ba3d38af34657a05ac55b06279ea6edd409e323dca8e"
|
||||
sha256: "3ba963161bd0fe395917ba881d320b9c4f6dd3c4a233da62ab18a5025c85f1e9"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.3"
|
||||
version: "2.4.0"
|
||||
url_launcher_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_windows
|
||||
sha256: "44cf3aabcedde30f2dba119a9dea3b0f2672fbe6fa96e85536251d678216b3c4"
|
||||
sha256: "3284b6d2ac454cf34f114e1d3319866fdd1e19cdc329999057e44ffe936cfa77"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.3"
|
||||
version: "3.1.4"
|
||||
uuid:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -1769,18 +1801,18 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vector_graphics
|
||||
sha256: "27d5fefe86fb9aace4a9f8375b56b3c292b64d8c04510df230f849850d912cb7"
|
||||
sha256: "44cc7104ff32563122a929e4620cf3efd584194eec6d1d913eb5ba593dbcf6de"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.15"
|
||||
version: "1.1.18"
|
||||
vector_graphics_codec:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vector_graphics_codec
|
||||
sha256: "2430b973a4ca3c4dbc9999b62b8c719a160100dcbae5c819bae0cacce32c9cdb"
|
||||
sha256: "99fd9fbd34d9f9a32efd7b6a6aae14125d8237b10403b422a6a6dfeac2806146"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.12"
|
||||
version: "1.1.13"
|
||||
vector_graphics_compiler:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -1809,18 +1841,18 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: video_player_android
|
||||
sha256: "391e092ba4abe2f93b3e625bd6b6a6ec7d7414279462c1c0ee42b5ab8d0a0898"
|
||||
sha256: "7018dbcb395e2bca0b9a898e73989e67c0c4a5db269528e1b036ca38bcca0d0b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.7.16"
|
||||
version: "2.7.17"
|
||||
video_player_avfoundation:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: video_player_avfoundation
|
||||
sha256: "33224c19775fd244be2d6e3dbd8e1826ab162877bd61123bf71890772119a2b7"
|
||||
sha256: "84b4752745eeccb6e75865c9aab39b3d28eb27ba5726d352d45db8297fbd75bc"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.6.5"
|
||||
version: "2.7.0"
|
||||
video_player_platform_interface:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -1833,10 +1865,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: video_player_web
|
||||
sha256: "881b375a934d8ebf868c7fb1423b2bfaa393a0a265fa3f733079a86536064a10"
|
||||
sha256: "3ef40ea6d72434edbfdba4624b90fd3a80a0740d260667d91e7ecd2d79e13476"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.3"
|
||||
version: "2.3.4"
|
||||
vm_service:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -1873,10 +1905,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: web_socket_channel
|
||||
sha256: "9f187088ed104edd8662ca07af4b124465893caf063ba29758f97af57e61da8f"
|
||||
sha256: "0b8e2457400d8a859b7b2030786835a28a8e80836ef64402abef392ff4f1d0e5"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.1"
|
||||
version: "3.0.2"
|
||||
webdriver:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -1897,10 +1929,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: win32
|
||||
sha256: "8b338d4486ab3fbc0ba0db9f9b4f5239b6697fcee427939a40e720cbb9ee0a69"
|
||||
sha256: b89e6e24d1454e149ab20fbb225af58660f0c0bf4475544650700d8e2da54aef
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.9.0"
|
||||
version: "5.11.0"
|
||||
window_manager:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -1946,10 +1978,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: yaml_edit
|
||||
sha256: e9c1a3543d2da0db3e90270dbb1e4eebc985ee5e3ffe468d83224472b2194a5f
|
||||
sha256: fb38626579fb345ad00e674e2af3a5c9b0cc4b9bfb8fd7f7ff322c7c9e62aef5
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.1"
|
||||
version: "2.2.2"
|
||||
sdks:
|
||||
dart: ">=3.7.0-0 <3.999.0"
|
||||
dart: ">=3.7.0 <3.999.0"
|
||||
flutter: ">=3.29.0"
|
||||
|
@ -22,6 +22,7 @@ dependencies:
|
||||
extended_text_field: ^16.0.0
|
||||
file_selector: ^1.0.3
|
||||
flex_color_scheme: ^8.1.1
|
||||
flutter_highlighter: ^0.1.0
|
||||
flutter_hooks: ^0.21.2
|
||||
flutter_markdown: ^0.7.6+2
|
||||
flutter_portal: ^1.1.4
|
||||
@ -47,6 +48,7 @@ dependencies:
|
||||
multi_split_view: ^3.2.2
|
||||
multi_trigger_autocomplete_plus:
|
||||
path: packages/multi_trigger_autocomplete_plus
|
||||
ollama_dart: ^0.2.2
|
||||
package_info_plus: ^8.3.0
|
||||
path: ^1.8.3
|
||||
path_provider: ^2.1.2
|
||||
|
Reference in New Issue
Block a user