import gradio as gr import os import subprocess from mistralai.client import MistralClient # --- 1. 환경 설정 --- API_KEY = os.environ.get("MISTRAL_API_KEY") CLIENT = None CODESTRAL_ENDPOINT = "https://codestral.mistral.ai/v1" if API_KEY: try: CLIENT = MistralClient(api_key=API_KEY, endpoint=CODESTRAL_ENDPOINT) print("Mistral API Client for Codestral initialized successfully.") except Exception as e: print(f"Error initializing Mistral Client: {e}") else: print("FATAL: MISTRAL_API_KEY is not set in Space Secrets.") # --- 2. 백엔드 핵심 기능 함수 --- def generate_c_code(description: str) -> str: if not CLIENT: return "Error: Mistral API key not configured." prompt = f"You are a C programming expert. Generate a complete, compilable C code for this request: '{description}'. ONLY output the raw C code, without any markdown formatting or explanations." messages = [{"role": "user", "content": prompt}] response = CLIENT.chat(model="codestral-latest", messages=messages) return response.choices[0].message.content.strip() def compile_and_run_c_code(code: str) -> str: try: with open("main.c", "w", encoding='utf-8') as f: f.write(code) compile_proc = subprocess.run(["gcc", "main.c", "-o", "main.out", "-lm", "-w"], capture_output=True, text=True, timeout=15) if compile_proc.returncode != 0: return f"--- COMPILATION FAILED ---\n{compile_proc.stderr}" run_proc = subprocess.run(["./main.out"], capture_output=True, text=True, timeout=15) if run_proc.returncode != 0: return f"--- RUNTIME ERROR ---\n{run_proc.stderr}" output = run_proc.stdout return f"--- EXECUTION SUCCEEDED ---\n{output}" if output.strip() else "--- EXECUTION SUCCEEDED ---\n(No output was produced)" except Exception as e: return f"--- SYSTEM ERROR ---\nAn unexpected error occurred: {str(e)}" def analyze_and_refactor_code(code: str, instruction: str) -> str: if not CLIENT: return "Error: Mistral API key not configured." prompt = f"""You are a senior C code reviewer. Analyze the following C code based on the user's instruction. Provide a clear, concise response. If refactoring, provide the complete improved code in a C code block. Instruction: '{instruction}' C Code to Analyze: ```c {code} ```""" messages = [{"role": "user", "content": prompt}] response = CLIENT.chat(model="codestral-latest", messages=messages) return response.choices[0].message.content # --- 3. 메인 이벤트 핸들러 --- def handle_instruction(code: str, instruction: str): if not instruction: return code, "Error: Instruction cannot be empty." lower_instruction = instruction.lower() # 'generate' 또는 'create'가 포함된 경우, 코드 에디터가 비어있어도 무조건 생성 if "generate" in lower_instruction or "create" in lower_instruction or "만들어줘" in lower_instruction: yield code, "Generating new code..." new_code = generate_c_code(instruction) yield new_code, "Code generation successful. New code is in the editor." return # 그 외의 경우, 코드 에디터가 비어있으면 에러 if not code: yield code, "Error: Code editor is empty. Please provide code to work with, or ask to 'generate' new code." return if "compile" in lower_instruction or "run" in lower_instruction: yield code, "Compiling and running..." result = compile_and_run_c_code(code) yield code, result else: # Refactor, analyze, add comments, etc. yield code, f"Analyzing code with instruction: '{instruction}'..." analysis_result = analyze_and_refactor_code(code, instruction) yield code, analysis_result # --- 4. Gradio UI 구성 (IDE 형태) --- with gr.Blocks(theme=gr.themes.Monochrome(primary_hue="indigo", secondary_hue="blue"), css="footer {visibility: hidden}") as demo: gr.Markdown("# 💻 The C-Codestral IDE Agent") with gr.Tabs(): with gr.TabItem("👨‍💻 IDE"): with gr.Row(): with gr.Column(scale=2): code_editor = gr.Code(label="C Code Editor", language="c", lines=25, interactive=True) with gr.Column(scale=1): instruction_box = gr.Textbox( label="Instruction", placeholder="e.g., 'Compile and run', 'Find bugs', 'Generate a factorial function'...", lines=3 ) execute_btn = gr.Button("Execute Instruction", variant="primary") output_box = gr.Textbox(label="Output / Console", lines=15, interactive=False, show_copy_button=True) execute_btn.click( fn=handle_instruction, inputs=[code_editor, instruction_box], outputs=[code_editor, output_box] ) with gr.TabItem("🛠️ MCP Tools API"): gr.Markdown("## Available MCP Tools\nThese APIs can be used by any MCP-compliant client.") with gr.Accordion("Tool: Generate C Code", open=False): gr.Interface(fn=generate_c_code, inputs="text", outputs=gr.Code(language="c", label="Generated C Code")) with gr.Accordion("Tool: Compile & Run C Code", open=False): gr.Interface(fn=compile_and_run_c_code, inputs=gr.Code(language="c"), outputs=gr.Textbox(label="Output")) with gr.Accordion("Tool: Analyze & Refactor C Code", open=False): gr.Interface(fn=analyze_and_refactor_code, inputs=[gr.Code(language="c"), "text"], outputs=gr.Markdown()) if __name__ == "__main__": demo.queue().launch()