Spaces:
Running
Running
| import textwrap | |
| class CodeGenerator: | |
| def generate_gradio_app(function_code: str, inputs: dict, output_desc: str) -> str: | |
| """ | |
| Generates the complete code for a Gradio application from a function snippet. | |
| Args: | |
| function_code: The source code of the main function (e.g. def count_r(word): ...) | |
| inputs: Dict describing inputs (e.g. {"word": "text"}) | |
| output_desc: Description of the output | |
| Returns: | |
| The complete source code for app.py | |
| """ | |
| # Simple analysis to find the function name (very naive for now) | |
| # We assume the code contains "def function_name(" | |
| import re | |
| match = re.search(r"def\s+([a-zA-Z_][a-zA-Z0-9_]*)\s*\(", function_code) | |
| func_name = match.group(1) if match else "main_function" | |
| # Mapping MCP/JSON types to Gradio types | |
| # For simplicity, we map everything to Text for now or use direct strings | |
| # TODO: Improve type mapping | |
| # Code construction | |
| template = f""" | |
| import gradio as gr | |
| import json | |
| # --- User Defined Logic --- | |
| {function_code} | |
| # --- Gradio Interface --- | |
| # Wrapper to handle types if necessary | |
| def wrapper(*args): | |
| result = {func_name}(*args) | |
| return str(result) # Force string output for simplicity | |
| # Gradio inputs configuration | |
| # Note: This part is generic for the MVP. | |
| # Ideally, iterate over 'inputs' to create corresponding Gradio components. | |
| iface = gr.Interface( | |
| fn=wrapper, | |
| inputs=[gr.Textbox(label=k) for k in {list(inputs.keys())}], | |
| outputs=gr.Textbox(label="{output_desc}"), | |
| title="Meta-MCP Generated Tool", | |
| description="Auto-generated by Meta-MCP Fractal" | |
| ) | |
| if __name__ == "__main__": | |
| iface.launch(mcp_server=True, show_error=True) | |
| """ | |
| return textwrap.dedent(template).strip() | |
| def generate_tool_module(function_code: str, inputs: dict, output_desc: str, tool_name: str, output_component: str = "text") -> str: | |
| """ | |
| Generates a Python module containing the tool logic and an interface factory. | |
| """ | |
| import re | |
| match = re.search(r"def\s+([a-zA-Z_][a-zA-Z0-9_]*)\s*\(", function_code) | |
| func_name = match.group(1) if match else "main_function" | |
| inputs_keys_str = str(list(inputs.keys())) | |
| # Output component mapping | |
| if output_component == "image": | |
| gradio_output = 'gr.Image(type="filepath", label="__OUTPUT_DESC__")' | |
| elif output_component == "audio": | |
| gradio_output = 'gr.Audio(type="filepath", label="__OUTPUT_DESC__")' | |
| elif output_component == "video": | |
| gradio_output = 'gr.Video(label="__OUTPUT_DESC__")' | |
| elif output_component == "html": | |
| gradio_output = 'gr.HTML(label="__OUTPUT_DESC__")' | |
| elif output_component == "json": | |
| gradio_output = 'gr.JSON(label="__OUTPUT_DESC__")' | |
| elif output_component == "file": | |
| gradio_output = 'gr.File(label="__OUTPUT_DESC__")' | |
| else: # text | |
| gradio_output = 'gr.Textbox(label="__OUTPUT_DESC__")' | |
| template = """ | |
| import gradio as gr | |
| import json | |
| from PIL import Image | |
| import numpy as np | |
| # --- User Defined Logic --- | |
| __FUNCTION_CODE__ | |
| # --- Interface Factory --- | |
| def create_interface(): | |
| return gr.Interface( | |
| fn=__FUNC_NAME__, | |
| inputs=[gr.Textbox(label=k) for k in __INPUTS_KEYS__], | |
| outputs=__GRADIO_OUTPUT__, | |
| title="__TOOL_NAME__", | |
| description="Auto-generated tool: __TOOL_NAME__" | |
| ) | |
| """ | |
| code = textwrap.dedent(template).strip() | |
| code = code.replace("__FUNCTION_CODE__", function_code) | |
| code = code.replace("__FUNC_NAME__", func_name) | |
| code = code.replace("__INPUTS_KEYS__", inputs_keys_str) | |
| code = code.replace("__GRADIO_OUTPUT__", gradio_output) # Dynamic component injection | |
| code = code.replace("__OUTPUT_DESC__", output_desc) | |
| code = code.replace("__TOOL_NAME__", tool_name) | |
| return code | |
| def generate_master_app() -> str: | |
| """ | |
| Generates the main app.py file. | |
| Uses a standard approach with simple dynamic import. | |
| """ | |
| template = """ | |
| import gradio as gr | |
| import os | |
| import sys | |
| import importlib | |
| # Configuration | |
| TOOLS_DIR = "tools" | |
| # Ensure tools directory exists and is a package | |
| if not os.path.exists(TOOLS_DIR): | |
| os.makedirs(TOOLS_DIR, exist_ok=True) | |
| with open(os.path.join(TOOLS_DIR, "__init__.py"), "w") as f: | |
| pass | |
| # Add current directory to path so 'import tools.xxx' works | |
| sys.path.append(os.path.dirname(os.path.abspath(__file__))) | |
| interfaces = [] | |
| names = [] | |
| print(f"π Starting Meta-MCP Toolbox...") | |
| print(f"π Scanning '{TOOLS_DIR}' directory...") | |
| # Scan and import tools | |
| try: | |
| for filename in sorted(os.listdir(TOOLS_DIR)): | |
| if filename.endswith(".py") and not filename.startswith("_"): | |
| module_name = filename[:-3] | |
| full_module_name = f"{TOOLS_DIR}.{module_name}" | |
| try: | |
| print(f" π Importing {full_module_name}...") | |
| # Standard dynamic import | |
| # Use reload to ensure latest version is taken if restarted | |
| module = importlib.import_module(full_module_name) | |
| importlib.reload(module) | |
| if hasattr(module, "create_interface"): | |
| # Create Gradio interface for this tool | |
| tool_interface = module.create_interface() | |
| interfaces.append(tool_interface) | |
| names.append(module_name) | |
| print(f" β Loaded {module_name}") | |
| else: | |
| print(f" β οΈ Module {module_name} has no create_interface()") | |
| except Exception as e: | |
| print(f" β Error loading {module_name}: {e}") | |
| import traceback | |
| traceback.print_exc() | |
| except Exception as e: | |
| print(f"Error scanning tools directory: {e}") | |
| # Final interface construction | |
| if not interfaces: | |
| demo = gr.Interface( | |
| fn=lambda x: "No tools loaded yet. Add a tool via Meta-MCP!", | |
| inputs="text", | |
| outputs="text", | |
| title="Empty Toolbox", | |
| description="This Space is ready to receive tools." | |
| ) | |
| else: | |
| demo = gr.TabbedInterface(interfaces, names) | |
| if __name__ == "__main__": | |
| demo.launch(mcp_server=True, show_error=True) | |
| """ | |
| return textwrap.dedent(template).strip() | |
| def generate_mcp_server_code(function_code: str) -> str: | |
| """ | |
| Generates an MCP server (FastMCP) instead of Gradio (Future feature). | |
| """ | |
| pass | |