diff --git a/lib/apitoolgen/tool_templates.dart b/lib/apitoolgen/tool_templates.dart index c36db4f2..3ecf0a3e 100644 --- a/lib/apitoolgen/tool_templates.dart +++ b/lib/apitoolgen/tool_templates.dart @@ -91,3 +91,22 @@ api_tool = { __all__ = ["api_tool"] """; + +class APIToolGenTemplateSelector { + static String getTemplate(String language, String agent) { + if (language == 'PYTHON') { + if (agent == 'MICROSOFT_AUTOGEN') { + return MICROSOFT_AUTOGEN_TOOL_FORMAT; + } else if (agent == 'LANGCHAIN') { + return LANGCHAIN_PYTHON_TOOL_FORMAT; + } + return GENERAL_PYTHON_TOOL_FORMAT; + } else if (language == 'JAVASCRIPT') { + if (agent == 'LANGCHAIN') { + return LANGCHAIN_JAVASCRIPT_TOOL_FORMAT; + } + return GENERAL_JAVASCRIPT_TOOL_FORMAT; + } + return 'NO_TEMPLATE'; + } +} diff --git a/lib/services/agentic_services/agents/agents.dart b/lib/services/agentic_services/agents/agents.dart index ae01f493..9b69197a 100644 --- a/lib/services/agentic_services/agents/agents.dart +++ b/lib/services/agentic_services/agents/agents.dart @@ -4,3 +4,4 @@ export 'stac2flutter.dart'; export 'stacgen.dart'; export 'stacmodifier.dart'; export 'apitool_funcgen.dart'; +export 'apitool_bodygen.dart'; diff --git a/lib/services/agentic_services/agents/apitool_bodygen.dart b/lib/services/agentic_services/agents/apitool_bodygen.dart new file mode 100644 index 00000000..34671956 --- /dev/null +++ b/lib/services/agentic_services/agents/apitool_bodygen.dart @@ -0,0 +1,61 @@ +import 'package:genai/agentic_engine/blueprint.dart'; + +const String _sysprompt = """ +YOu are an expert API Tool Format Corrector Agent + +An API tool is a predefined or dynamically generated interface that the AI can call to perform specific external actions—such as fetching data, executing computations, or triggering real-world services—through an Application Programming Interface (API). + +You will be provided with a partially complete API tool template that will contain the api calling function named func and the tool definition +Your job is to correct any mistakes and provide the correct output. + +The template will contain the following variables (A Variable is marked by :: +Wherever you find this pattern replace it with the appropriate values) +`TOOL_NAME`: The name of the API Tool, infer it from the function code +`TOOL_DESCRIPTION`: The Description of the Tool, generate it based on the tool name +`TOOL_PARAMS`: The example of parameters have been provided below, infer the parameters needed from the func body, it must be a dictionary +`REQUIRED_PARAM_NAMES`: infer waht parameters are required and add thier names in a list +`INPUT_SCHEMA`: if this variable exists, then create a StructuredTool or DynamicStructuredTool schema of the input according to the language of the tool itself. + +this is the general format of parameters: +"ARG_NAME": { + "type": "ARG_TYPE", + "description: "ARG_DESC" +} + +ALWAYS return the output as code only and do not start or begin with any introduction or conclusion. ONLY THE CODE. + +Here's the Template: +``` +:TEMPLATE: +``` +"""; + +class ApiToolBodyGen extends APIDashAIAgent { + @override + String get agentName => 'APITOOL_BODYGEN'; + + @override + String getSystemPrompt() { + return _sysprompt; + } + + @override + Future validator(String aiResponse) async { + //Add any specific validations here as needed + return true; + } + + @override + Future outputFormatter(String validatedResponse) async { + validatedResponse = validatedResponse + .replaceAll('```python', '') + .replaceAll('```python\n', '') + .replaceAll('```javascript', '') + .replaceAll('```javascript\n', '') + .replaceAll('```', ''); + + return { + 'TOOL': validatedResponse, + }; + } +} diff --git a/lib/services/agentic_services/agents/apitool_funcgen.dart b/lib/services/agentic_services/agents/apitool_funcgen.dart index 022b09e6..5bb862d4 100644 --- a/lib/services/agentic_services/agents/apitool_funcgen.dart +++ b/lib/services/agentic_services/agents/apitool_funcgen.dart @@ -40,6 +40,13 @@ class APIToolFunctionGenerator extends APIDashAIAgent { @override Future outputFormatter(String validatedResponse) async { + validatedResponse = validatedResponse + .replaceAll('```python', '') + .replaceAll('```python\n', '') + .replaceAll('```javascript', '') + .replaceAll('```javascript\n', '') + .replaceAll('```', ''); + return { 'FUNC': validatedResponse, }; diff --git a/lib/services/agentic_services/agents/stacgen.dart b/lib/services/agentic_services/agents/stacgen.dart index c59d7d7b..c6281d0b 100644 --- a/lib/services/agentic_services/agents/stacgen.dart +++ b/lib/services/agentic_services/agents/stacgen.dart @@ -224,6 +224,8 @@ circleAvatar has a field backgroundImage which takes the image url directly. no DO NOT START OR END THE RESPONSE WITH ANYTHING ELSE. I WANT PURE FLutter-SDUI OUTPUT +Generally wrap the whole thing with a SingleChildScrollView so that the whole thing is scrollable + """; class StacGenBot extends APIDashAIAgent { diff --git a/lib/widgets/ai_toolgen_widgets.dart b/lib/widgets/ai_toolgen_widgets.dart index b5320709..a815febc 100644 --- a/lib/widgets/ai_toolgen_widgets.dart +++ b/lib/widgets/ai_toolgen_widgets.dart @@ -1,6 +1,8 @@ import 'package:apidash/apitoolgen/request_consolidator.dart'; +import 'package:apidash/apitoolgen/tool_templates.dart'; import 'package:apidash/consts.dart'; import 'package:apidash/services/agentic_services/agent_caller.dart'; +import 'package:apidash/services/agentic_services/agents/apitool_bodygen.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'; @@ -27,16 +29,56 @@ class _GenerateToolDialogState extends ConsumerState { int index = 0; TextEditingController controller = TextEditingController(); - generateAPITool(String lang) async { + String selectedLanguage = 'PYTHON'; + String selectedAgent = 'GEMINI'; + String? generatedToolCode = ''; + + generateAPITool() async { + setState(() { + generatedToolCode = null; + }); final x = await APIDashAgentCaller.instance.call( APIToolFunctionGenerator(), ref: ref, input: AgentInputs(variables: { 'REQDATA': widget.requestDesc.generateREQDATA, - 'TARGET_LANGUAGE': lang, + 'TARGET_LANGUAGE': selectedLanguage, }), ); - print(x); + if (x == null) { + setState(() { + generatedToolCode = ''; + }); + print("ToolGeneration Failed"); //TODO: Make Alert + return; + } + + String toolCode = x!['FUNC']; + + print(toolCode); + + //TODO: Integrate into tool + final toolres = await APIDashAgentCaller.instance.call( + ApiToolBodyGen(), + ref: ref, + input: AgentInputs(variables: { + 'TEMPLATE': APIToolGenTemplateSelector.getTemplate( + selectedLanguage, selectedAgent) + .substitutePromptVariable('FUNC', toolCode), + }), + ); + if (toolres == null) { + setState(() { + generatedToolCode = ''; + }); + print("ToolGeneration Failed"); //TODO: Make Alert + return; + } + String toolDefinition = toolres!['TOOL']; + + setState(() { + generatedToolCode = toolDefinition; + }); } @override @@ -44,31 +86,20 @@ class _GenerateToolDialogState extends ConsumerState { return Container( height: 600, width: MediaQuery.of(context).size.width * 0.8, - child: IndexedStack( - index: index, + child: Row( 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, - ), - ), - ), - ), + Expanded(child: ToolRequirementSelectorPage( + onGenerateCallback: (agent, lang) { + setState(() { + selectedLanguage = lang; + selectedAgent = agent; + }); + generateAPITool(); + }, + )), + GeneratedToolCodeCopyPage( + toolCode: generatedToolCode, + language: 'javascript', ), ], ), @@ -77,7 +108,9 @@ class _GenerateToolDialogState extends ConsumerState { } class ToolRequirementSelectorPage extends StatefulWidget { - const ToolRequirementSelectorPage({super.key}); + final Function(String agent, String lang) onGenerateCallback; + const ToolRequirementSelectorPage( + {super.key, required this.onGenerateCallback}); @override State createState() => @@ -150,7 +183,7 @@ class _ToolRequirementSelectorPageState //AutoGen is Python-Only if (agentFramework == 'MICROSOFT_AUTOGEN') { - targetLanguage = 'JAVASCRIPT'; + targetLanguage = 'PYTHON'; } }); }, @@ -179,7 +212,7 @@ class _ToolRequirementSelectorPageState //AutoGen is Python-Only if (agentFramework == 'MICROSOFT_AUTOGEN') { - targetLanguage = 'JAVASCRIPT'; + targetLanguage = 'PYTHON'; } }); }, @@ -191,7 +224,9 @@ class _ToolRequirementSelectorPageState padding: kPh12, minimumSize: const Size(44, 44), ), - onPressed: () {}, + onPressed: () { + widget.onGenerateCallback(agentFramework, targetLanguage); + }, icon: Icon( Icons.token_outlined, ), @@ -208,7 +243,7 @@ class _ToolRequirementSelectorPageState } class GeneratedToolCodeCopyPage extends StatelessWidget { - final String toolCode; + final String? toolCode; final String language; const GeneratedToolCodeCopyPage( {super.key, required this.toolCode, required this.language}); @@ -219,7 +254,14 @@ class GeneratedToolCodeCopyPage extends StatelessWidget { ? kLightCodeTheme : kDarkCodeTheme; - if (toolCode.isEmpty) { + if (toolCode == null) { + return SendingWidget( + startSendingTime: DateTime.now(), + showTimeElapsed: false, + ); + } + + if (toolCode!.isEmpty) { return Padding( padding: const EdgeInsets.only(right: 40), child: Center( @@ -235,22 +277,24 @@ class GeneratedToolCodeCopyPage extends StatelessWidget { 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, + width: MediaQuery.of(context).size.width * 0.50, child: Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ CopyButton( - toCopy: toolCode, + toCopy: toolCode!, showLabel: true, ), Expanded( child: SingleChildScrollView( - child: CodePreviewer( - code: toolCode, - theme: codeTheme, - language: language.toLowerCase(), - textStyle: kCodeStyle, + child: Container( + width: double.infinity, + child: CodePreviewer( + code: toolCode!, + theme: codeTheme, + language: language.toLowerCase(), + textStyle: kCodeStyle, + ), ), ), ),