Some MinorRefactors & AIToolGen Dialog Implementation

This commit is contained in:
Manas Hejmadi
2025-05-04 02:05:28 +05:30
parent c1246b538d
commit 6382883b8c
5 changed files with 374 additions and 125 deletions

View File

@@ -91,7 +91,7 @@ ENDPOINT: $endpoint
HEADERS: ${headersStr.isEmpty ? '{}' : headersStr}
$queryParamStr
$bodyDetails
$responseDetails
""";
}
}

View File

@@ -0,0 +1,261 @@
import 'package:apidash/apitoolgen/request_consolidator.dart';
import 'package:apidash/consts.dart';
import 'package:apidash/services/agentic_services/agent_caller.dart';
import 'package:apidash/services/agentic_services/agents/apitool_funcgen.dart';
import 'package:apidash/widgets/ai_ui_desginer_widgets.dart';
import 'package:apidash/widgets/button_copy.dart';
import 'package:apidash/widgets/previewer_code.dart';
import 'package:apidash/widgets/widget_sending.dart';
import 'package:apidash_design_system/tokens/tokens.dart';
import 'package:apidash_design_system/widgets/popup_menu.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:genai/agentic_engine/blueprint.dart';
class GenerateToolDialog extends ConsumerStatefulWidget {
final APIDashRequestDescription requestDesc;
const GenerateToolDialog({
super.key,
required this.requestDesc,
});
@override
ConsumerState<GenerateToolDialog> createState() => _GenerateToolDialogState();
}
class _GenerateToolDialogState extends ConsumerState<GenerateToolDialog> {
int index = 0;
TextEditingController controller = TextEditingController();
generateAPITool(String lang) async {
final x = await APIDashAgentCaller.instance.call(
APIToolFunctionGenerator(),
ref: ref,
input: AgentInputs(variables: {
'REQDATA': widget.requestDesc.generateREQDATA,
'TARGET_LANGUAGE': lang,
}),
);
print(x);
}
@override
Widget build(BuildContext context) {
return Container(
height: 600,
width: MediaQuery.of(context).size.width * 0.8,
child: IndexedStack(
index: index,
children: [
Row(
children: [
Expanded(child: ToolRequirementSelectorPage()),
GeneratedToolCodeCopyPage(
toolCode: r"""""",
language: 'javascript',
),
],
),
SizedBox(
child: Center(
child: Padding(
padding: const EdgeInsets.only(top: 40.0),
child: Container(
height: 500,
child: SendingWidget(
startSendingTime: DateTime.now(),
showTimeElapsed: false,
),
),
),
),
),
],
),
);
}
}
class ToolRequirementSelectorPage extends StatefulWidget {
const ToolRequirementSelectorPage({super.key});
@override
State<ToolRequirementSelectorPage> createState() =>
_ToolRequirementSelectorPageState();
}
class _ToolRequirementSelectorPageState
extends State<ToolRequirementSelectorPage> {
String targetLanguage = 'PYTHON';
String agentFramework = 'GEMINI';
Map frameworkMapping = {
'GEMINI': 'Gemini',
'OPENAI': 'OpenAI',
'LANGCHAIN': 'LangChain',
'MICROSOFT_AUTOGEN': 'Microsoft AutoGen',
'MISTRAL': 'Mistral',
'ANTRHOPIC': 'Anthropic',
};
Map languageMapping = {
'PYTHON': 'Python 3',
'JAVASCRIPT': 'JavaScript / NodeJS'
};
@override
Widget build(BuildContext context) {
return Container(
width: MediaQuery.of(context).size.width * 0.4, // Large dialog
padding: EdgeInsets.all(30),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Generate API Tool",
style: TextStyle(
fontSize: 24,
color: Colors.white,
),
),
kVSpacer5,
Padding(
padding: EdgeInsets.only(left: 3),
child: Text(
"Select an agent framework & language",
style: TextStyle(color: Colors.white60, fontSize: 15),
),
),
kVSpacer20,
Padding(
padding: EdgeInsets.only(left: 3),
child: Text(
"Agent Framework",
style: TextStyle(color: Colors.white60),
),
),
kVSpacer8,
ADPopupMenu<String>(
value: frameworkMapping[agentFramework],
values: [
...frameworkMapping.keys
.map((e) => (e.toString(), frameworkMapping[e].toString())),
],
width: MediaQuery.of(context).size.width * 0.35,
tooltip: '',
onChanged: (x) {
setState(() {
agentFramework = x ?? 'OPENAI';
//AutoGen is Python-Only
if (agentFramework == 'MICROSOFT_AUTOGEN') {
targetLanguage = 'JAVASCRIPT';
}
});
},
isOutlined: true,
),
kVSpacer20,
Padding(
padding: EdgeInsets.only(left: 3),
child: Text(
"Target Language",
style: TextStyle(color: Colors.white60),
),
),
kVSpacer8,
ADPopupMenu<String>(
value: languageMapping[targetLanguage],
values: [
...languageMapping.keys
.map((e) => (e.toString(), languageMapping[e].toString())),
],
width: MediaQuery.of(context).size.width * 0.35,
tooltip: '',
onChanged: (x) {
setState(() {
targetLanguage = x ?? 'PYTHON';
//AutoGen is Python-Only
if (agentFramework == 'MICROSOFT_AUTOGEN') {
targetLanguage = 'JAVASCRIPT';
}
});
},
isOutlined: true,
),
kVSpacer20,
FilledButton.tonalIcon(
style: FilledButton.styleFrom(
padding: kPh12,
minimumSize: const Size(44, 44),
),
onPressed: () {},
icon: Icon(
Icons.token_outlined,
),
label: const SizedBox(
child: Text(
"Generate Tool",
),
),
),
],
),
);
}
}
class GeneratedToolCodeCopyPage extends StatelessWidget {
final String toolCode;
final String language;
const GeneratedToolCodeCopyPage(
{super.key, required this.toolCode, required this.language});
@override
Widget build(BuildContext context) {
var codeTheme = Theme.of(context).brightness == Brightness.light
? kLightCodeTheme
: kDarkCodeTheme;
if (toolCode.isEmpty) {
return Padding(
padding: const EdgeInsets.only(right: 40),
child: Center(
child: Icon(
Icons.token_outlined,
color: Colors.white12,
size: 500,
),
),
);
}
return Container(
color: const Color.fromARGB(255, 28, 28, 28),
padding: EdgeInsets.all(20),
constraints: BoxConstraints(maxWidth: 700),
width: MediaQuery.of(context).size.width * 0.55,
child: Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
CopyButton(
toCopy: toolCode,
showLabel: true,
),
Expanded(
child: SingleChildScrollView(
child: CodePreviewer(
code: toolCode,
theme: codeTheme,
language: language.toLowerCase(),
textStyle: kCodeStyle,
),
),
),
],
),
);
}
}

View File

@@ -8,10 +8,9 @@ import 'package:flutter/services.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:genai/agentic_engine/blueprint.dart';
import 'package:stac/stac.dart' as stac;
import '../services/agentic_services/agents/agents.dart';
void showCustomDialog(BuildContext context, String content) {
void showCustomDialog(BuildContext context, Widget dialogContent) {
showDialog(
context: context,
builder: (BuildContext context) {
@@ -20,26 +19,24 @@ void showCustomDialog(BuildContext context, String content) {
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12.0),
),
child: DialogContents(
content: content,
),
child: dialogContent,
);
},
);
}
class DialogContents extends ConsumerStatefulWidget {
class GenerateUIDialog extends ConsumerStatefulWidget {
final String content;
const DialogContents({
const GenerateUIDialog({
super.key,
required this.content,
});
@override
ConsumerState<DialogContents> createState() => _DialogContentsState();
ConsumerState<GenerateUIDialog> createState() => _GenerateUIDialogState();
}
class _DialogContentsState extends ConsumerState<DialogContents> {
class _GenerateUIDialogState extends ConsumerState<GenerateUIDialog> {
int index = 0;
TextEditingController controller = TextEditingController();

View File

@@ -1,3 +1,10 @@
import 'dart:convert';
import 'package:apidash/apitoolgen/request_consolidator.dart';
import 'package:apidash/providers/collection_providers.dart';
import 'package:apidash/widgets/ai_toolgen_widgets.dart';
import 'package:apidash/widgets/ai_ui_desginer_widgets.dart';
import 'package:apidash_core/apidash_core.dart';
import 'package:apidash_design_system/apidash_design_system.dart';
import 'package:flutter/foundation.dart';
@@ -5,9 +12,11 @@ import 'package:flutter/material.dart';
import 'package:apidash/utils/utils.dart';
import 'package:apidash/widgets/widgets.dart';
import 'package:apidash/consts.dart';
import 'package:genai/genai.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'button_share.dart';
class ResponseBodySuccess extends StatefulWidget {
class ResponseBodySuccess extends ConsumerStatefulWidget {
const ResponseBodySuccess({
super.key,
required this.mediaType,
@@ -31,10 +40,11 @@ class ResponseBodySuccess extends StatefulWidget {
final AIRequestModel? aiRequestModel;
@override
State<ResponseBodySuccess> createState() => _ResponseBodySuccessState();
ConsumerState<ResponseBodySuccess> createState() =>
_ResponseBodySuccessState();
}
class _ResponseBodySuccessState extends State<ResponseBodySuccess> {
class _ResponseBodySuccessState extends ConsumerState<ResponseBodySuccess> {
int segmentIdx = 0;
@override
@@ -61,6 +71,97 @@ class _ResponseBodySuccessState extends State<ResponseBodySuccess> {
padding: kP10,
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
FilledButton.tonalIcon(
style: FilledButton.styleFrom(
padding: kPh12,
minimumSize: const Size(44, 44),
),
onPressed: () async {
final requestModel = ref.watch(
selectedRequestModelProvider
.select((value) => value?.httpRequestModel));
final responseModel = ref.watch(
selectedRequestModelProvider
.select((value) => value?.httpResponseModel));
if (requestModel == null) return;
if (responseModel == null) {
print("AA");
return;
}
String? bodyTXT;
Map? bodyJSON;
List<Map>? bodyFormData;
if (requestModel.bodyContentType ==
ContentType.formdata) {
bodyFormData = requestModel.formDataMapList;
} else if (requestModel.bodyContentType ==
ContentType.json) {
bodyJSON = jsonDecode(requestModel.body.toString());
} else {
bodyTXT = requestModel.body!;
}
final reqDesModel = APIDashRequestDescription(
endpoint: requestModel.url,
method: requestModel.method.name.toUpperCase(),
responseType: responseModel.contentType.toString(),
headers: requestModel.headersMap,
response: responseModel.body,
formData: bodyFormData,
bodyTXT: bodyTXT,
bodyJSON: bodyJSON,
);
print("GT2");
showCustomDialog(
context,
GenerateToolDialog(
requestDesc: reqDesModel,
),
);
},
icon: Icon(
Icons.token_outlined,
),
label: const SizedBox(
child: Text(
"Generate Tool",
),
),
),
kHSpacer10,
FilledButton.tonalIcon(
style: FilledButton.styleFrom(
padding: kPh12,
minimumSize: const Size(44, 44),
),
onPressed: () {
final model = ref.watch(selectedRequestModelProvider
.select((value) => value?.httpResponseModel));
showCustomDialog(
context,
GenerateUIDialog(content: model?.formattedBody ?? ""),
);
},
icon: Icon(
Icons.generating_tokens,
),
label: const SizedBox(
child: Text(
kLabelGenerateUI,
),
),
),
kHSpacer10,
],
),
kVSpacer10,
Row(
children: [
(widget.options == kRawBodyViewOptions)

View File

@@ -1,20 +1,9 @@
import 'dart:convert';
import 'package:apidash/apitoolgen/request_consolidator.dart';
import 'package:apidash/providers/collection_providers.dart';
import 'package:apidash/services/agentic_services/agent_caller.dart';
import 'package:apidash/services/agentic_services/agents/apitool_funcgen.dart';
import 'package:apidash/widgets/ai_ui_desginer_widgets.dart';
import 'package:apidash_core/apidash_core.dart';
import 'package:flutter/material.dart';
import 'package:apidash_design_system/apidash_design_system.dart';
import 'package:apidash/utils/utils.dart';
import 'package:apidash/consts.dart';
import 'package:genai/agentic_engine/blueprint.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'button_clear_response.dart';
class ResponsePaneHeader extends ConsumerWidget {
class ResponsePaneHeader extends StatelessWidget {
const ResponsePaneHeader({
super.key,
this.responseStatus,
@@ -29,7 +18,7 @@ class ResponsePaneHeader extends ConsumerWidget {
final VoidCallback? onClearResponse;
@override
Widget build(BuildContext context, WidgetRef ref) {
Widget build(BuildContext context) {
final bool showClearButton = onClearResponse != null;
return Padding(
padding: kPv8,
@@ -71,105 +60,6 @@ class ResponsePaneHeader extends ConsumerWidget {
: const SizedBox.shrink(),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
FilledButton.tonalIcon(
style: FilledButton.styleFrom(
padding: kPh12,
minimumSize: const Size(44, 44),
),
onPressed: () async {
final requestModel = ref.watch(selectedRequestModelProvider
.select((value) => value?.httpRequestModel));
final responseModel = ref.watch(selectedRequestModelProvider
.select((value) => value?.httpResponseModel));
if (requestModel == null) return;
if (responseModel == null) {
print("AA");
return;
}
String? bodyTXT;
Map? bodyJSON;
List<Map>? bodyFormData;
if (requestModel.bodyContentType == ContentType.formdata) {
bodyFormData = requestModel.formDataMapList;
} else if (requestModel.bodyContentType ==
ContentType.json) {
bodyJSON = jsonDecode(requestModel.body.toString());
} else {
bodyTXT = requestModel.body!;
}
final reqDesModel = APIDashRequestDescription(
endpoint: requestModel.url,
method: requestModel.method.name.toUpperCase(),
responseType: responseModel.contentType.toString(),
headers: requestModel.headersMap,
response: responseModel.body,
formData: bodyFormData,
bodyTXT: bodyTXT,
bodyJSON: bodyJSON,
);
print(reqDesModel.generateREQDATA);
return;
final x = await APIDashAgentCaller.instance.call(
APIToolFunctionGenerator(),
ref: ref,
input: AgentInputs(variables: {
'REQDATA': reqDesModel.generateREQDATA,
'TARGET_LANGUAGE': 'JAVASCRIPT'
}),
);
print(x);
// print(reqDesModel.generateREQDATA);
// final model = ref.watch(selectedRequestModelProvider
// .select((value) => value?.httpResponseModel));
// showCustomDialog(context, model?.formattedBody ?? "");
},
icon: Icon(
Icons.token_outlined,
),
label: const SizedBox(
child: Text(
"Generate Tool",
),
),
),
kHSpacer10,
FilledButton.tonalIcon(
style: FilledButton.styleFrom(
padding: kPh12,
minimumSize: const Size(44, 44),
),
onPressed: () {
final model = ref.watch(selectedRequestModelProvider
.select((value) => value?.httpResponseModel));
if (model == null) return;
final body = (model.sseOutput?.isNotEmpty ?? false)
? model.sseOutput?.join("\n")
: model.formattedBody ?? model.body;
showCustomDialog(context, body ?? "");
},
icon: Icon(
Icons.generating_tokens,
),
label: const SizedBox(
child: Text(
kLabelGenerateUI,
),
),
),
kHSpacer10,
],
)
],
),
),