Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -4,6 +4,7 @@ import subprocess
|
|
| 4 |
import requests
|
| 5 |
import json
|
| 6 |
import re
|
|
|
|
| 7 |
|
| 8 |
# --- 1. 환경 설정 및 API 호출 함수 ---
|
| 9 |
API_KEY = os.environ.get("MISTRAL_API_KEY")
|
|
@@ -17,24 +18,19 @@ def call_mistral_api(messages):
|
|
| 17 |
if not API_KEY: return "Error: MISTRAL_API_KEY is not configured."
|
| 18 |
data = {"model": "codestral-latest", "messages": messages}
|
| 19 |
try:
|
| 20 |
-
response = requests.post(CODESTRAL_ENDPOINT, headers=HEADERS, data=json.dumps(data), timeout=
|
| 21 |
response.raise_for_status()
|
| 22 |
return response.json()["choices"][0]["message"]["content"]
|
| 23 |
except requests.exceptions.RequestException as e:
|
| 24 |
return f"API Call Error: {e}"
|
| 25 |
|
| 26 |
-
# --- 2. 백엔드 핵심 기능
|
| 27 |
def parse_code_from_response(response_text: str) -> str | None:
|
| 28 |
-
"""LLM 응답에서 C 코드 블록을 추출합니다."""
|
| 29 |
match = re.search(r'```c\n(.*?)\n```', response_text, re.DOTALL)
|
| 30 |
if match:
|
| 31 |
return match.group(1).strip()
|
| 32 |
return None
|
| 33 |
|
| 34 |
-
def generate_c_code(description: str) -> str:
|
| 35 |
-
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."
|
| 36 |
-
return call_mistral_api([{"role": "user", "content": prompt}])
|
| 37 |
-
|
| 38 |
def compile_and_run_c_code(code: str) -> str:
|
| 39 |
try:
|
| 40 |
with open("main.c", "w", encoding='utf-8') as f: f.write(code)
|
|
@@ -46,55 +42,97 @@ def compile_and_run_c_code(code: str) -> str:
|
|
| 46 |
return f"--- EXECUTION SUCCEEDED ---\n{output}" if output.strip() else "--- EXECUTION SUCCEEDED ---\n(No output was produced)"
|
| 47 |
except Exception as e: return f"--- SYSTEM ERROR ---\nAn unexpected error occurred: {str(e)}"
|
| 48 |
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 52 |
|
| 53 |
-
|
| 54 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 55 |
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
|
| 61 |
-
return code, analysis_result
|
| 62 |
-
|
| 63 |
-
# --- 3. Gradio UI 구성 (안정적인 탭 구조 + 지능형 파싱) ---
|
| 64 |
with gr.Blocks(theme=gr.themes.Monochrome(primary_hue="indigo", secondary_hue="blue"), css="footer {visibility: hidden}") as demo:
|
| 65 |
-
gr.Markdown("# 💻 The C-Codestral IDE Agent
|
| 66 |
|
| 67 |
with gr.Tabs():
|
| 68 |
-
with gr.TabItem("👨💻 IDE"):
|
| 69 |
-
with gr.Row():
|
| 70 |
with gr.Column(scale=2):
|
| 71 |
-
code_editor = gr.Code(label="C Code Editor", language="c", lines=
|
| 72 |
|
| 73 |
with gr.Column(scale=1):
|
| 74 |
-
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
|
| 87 |
-
# 이벤트 핸들러 연결
|
| 88 |
-
gen_btn.click(fn=generate_c_code, inputs=[gen_instr], outputs=[code_editor])
|
| 89 |
-
ana_btn.click(fn=analyze_and_refactor_code, inputs=[code_editor, ana_instr], outputs=[code_editor, output_box])
|
| 90 |
-
run_btn.click(fn=compile_and_run_c_code, inputs=[code_editor], outputs=[output_box])
|
| 91 |
-
|
| 92 |
-
with gr.TabItem("🛠️ MCP Tools"):
|
| 93 |
-
gr.Markdown("## Available MCP Tools for other Agents")
|
| 94 |
with gr.Accordion("Tool: Generate C Code", open=False):
|
| 95 |
-
|
|
|
|
|
|
|
|
|
|
| 96 |
with gr.Accordion("Tool: Compile & Run C Code", open=False):
|
| 97 |
-
|
|
|
|
|
|
|
| 98 |
|
| 99 |
if __name__ == "__main__":
|
| 100 |
demo.queue().launch()
|
|
|
|
| 4 |
import requests
|
| 5 |
import json
|
| 6 |
import re
|
| 7 |
+
import time
|
| 8 |
|
| 9 |
# --- 1. 환경 설정 및 API 호출 함수 ---
|
| 10 |
API_KEY = os.environ.get("MISTRAL_API_KEY")
|
|
|
|
| 18 |
if not API_KEY: return "Error: MISTRAL_API_KEY is not configured."
|
| 19 |
data = {"model": "codestral-latest", "messages": messages}
|
| 20 |
try:
|
| 21 |
+
response = requests.post(CODESTRAL_ENDPOINT, headers=HEADERS, data=json.dumps(data), timeout=45)
|
| 22 |
response.raise_for_status()
|
| 23 |
return response.json()["choices"][0]["message"]["content"]
|
| 24 |
except requests.exceptions.RequestException as e:
|
| 25 |
return f"API Call Error: {e}"
|
| 26 |
|
| 27 |
+
# --- 2. 백엔드 핵심 기능 (파서 포함) ---
|
| 28 |
def parse_code_from_response(response_text: str) -> str | None:
|
|
|
|
| 29 |
match = re.search(r'```c\n(.*?)\n```', response_text, re.DOTALL)
|
| 30 |
if match:
|
| 31 |
return match.group(1).strip()
|
| 32 |
return None
|
| 33 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 34 |
def compile_and_run_c_code(code: str) -> str:
|
| 35 |
try:
|
| 36 |
with open("main.c", "w", encoding='utf-8') as f: f.write(code)
|
|
|
|
| 42 |
return f"--- EXECUTION SUCCEEDED ---\n{output}" if output.strip() else "--- EXECUTION SUCCEEDED ---\n(No output was produced)"
|
| 43 |
except Exception as e: return f"--- SYSTEM ERROR ---\nAn unexpected error occurred: {str(e)}"
|
| 44 |
|
| 45 |
+
# --- 3. 진짜 '지능형' 에이전트 로직 ---
|
| 46 |
+
def intelligent_agent_ide(initial_code: str, full_instruction: str):
|
| 47 |
+
if not full_instruction:
|
| 48 |
+
yield initial_code, "Error: Instruction cannot be empty."
|
| 49 |
+
return
|
| 50 |
+
|
| 51 |
+
# 'and', 'then', ',' 등을 기준으로 명령어를 여러 단계로 분리
|
| 52 |
+
tasks = [task.strip() for task in re.split(r'\s+and\s+|\s*,\s*then\s*|\s*그리고\s*', full_instruction, flags=re.IGNORECASE)]
|
| 53 |
|
| 54 |
+
current_code = initial_code
|
| 55 |
+
output_log = []
|
| 56 |
+
step = 1
|
| 57 |
+
|
| 58 |
+
for task in tasks:
|
| 59 |
+
lower_task = task.lower()
|
| 60 |
+
output_log.append(f"▶ Step {step}: Executing '{task}'...")
|
| 61 |
+
yield current_code, "\n".join(output_log)
|
| 62 |
+
time.sleep(0.5)
|
| 63 |
+
|
| 64 |
+
# 1. 생성 (Generation)
|
| 65 |
+
if "generate" in lower_task or "create" in lower_task or "만들어줘" in lower_task:
|
| 66 |
+
prompt = f"Generate a complete, compilable C code for this request: '{task}'. ONLY output the raw C code, without markdown or explanations."
|
| 67 |
+
new_code = call_mistral_api([{"role": "user", "content": prompt}])
|
| 68 |
+
current_code = new_code if new_code and "Error" not in new_code else current_code
|
| 69 |
+
output_log.append(f"✅ Code generated and updated in the editor.")
|
| 70 |
+
yield current_code, "\n".join(output_log)
|
| 71 |
+
|
| 72 |
+
# 2. 컴파일 및 실행 (Compile & Run)
|
| 73 |
+
elif "compile" in lower_task or "run" in lower_task or "실행" in lower_task:
|
| 74 |
+
if not current_code:
|
| 75 |
+
output_log.append("❌ Error: Code is empty. Cannot compile.")
|
| 76 |
+
yield current_code, "\n".join(output_log)
|
| 77 |
+
break
|
| 78 |
+
result = compile_and_run_c_code(current_code)
|
| 79 |
+
output_log.append(result)
|
| 80 |
+
yield current_code, "\n".join(output_log)
|
| 81 |
+
|
| 82 |
+
# 3. 분석/리팩토링 (Analyze/Refactor)
|
| 83 |
+
else:
|
| 84 |
+
if not current_code:
|
| 85 |
+
output_log.append("❌ Error: Code is empty. Cannot analyze.")
|
| 86 |
+
yield current_code, "\n".join(output_log)
|
| 87 |
+
break
|
| 88 |
+
prompt = f"You are a senior C code reviewer. Fulfill this instruction: '{task}'. If you refactor or change the code, YOU MUST provide the complete, new code in a ```c code block. \n\nC Code to Analyze:\n```c\n{current_code}\n```"
|
| 89 |
+
analysis_result = call_mistral_api([{"role": "user", "content": prompt}])
|
| 90 |
+
|
| 91 |
+
refactored_code = parse_code_from_response(analysis_result)
|
| 92 |
+
if refactored_code:
|
| 93 |
+
current_code = refactored_code
|
| 94 |
+
output_log.append(f"✅ Code refactored and updated in the editor.")
|
| 95 |
+
output_log.append(f"🔎 Analysis Result:\n{analysis_result}")
|
| 96 |
+
yield current_code, "\n".join(output_log)
|
| 97 |
+
|
| 98 |
+
step += 1
|
| 99 |
|
| 100 |
+
output_log.append("\n--- All tasks complete. ---")
|
| 101 |
+
yield current_code, "\n".join(output_log)
|
| 102 |
+
|
| 103 |
+
|
| 104 |
+
# --- 4. 통합된 Gradio UI ---
|
|
|
|
|
|
|
|
|
|
| 105 |
with gr.Blocks(theme=gr.themes.Monochrome(primary_hue="indigo", secondary_hue="blue"), css="footer {visibility: hidden}") as demo:
|
| 106 |
+
gr.Markdown("# 💻 The True C-Codestral IDE Agent")
|
| 107 |
|
| 108 |
with gr.Tabs():
|
| 109 |
+
with gr.TabItem("👨💻 IDE Agent"):
|
| 110 |
+
with gr.Row(equal_height=True):
|
| 111 |
with gr.Column(scale=2):
|
| 112 |
+
code_editor = gr.Code(label="C Code Editor", language="c", lines=28, interactive=True, value='#include <stdio.h>\n\nint main() {\n printf("Hello, World!\\n");\n return 0;\n}')
|
| 113 |
|
| 114 |
with gr.Column(scale=1):
|
| 115 |
+
instruction_box = gr.Textbox(label="Instruction", placeholder="e.g., 'Refactor this code for readability, and then compile it'", lines=4)
|
| 116 |
+
execute_btn = gr.Button("Execute", variant="primary", size="lg")
|
| 117 |
+
output_box = gr.Textbox(label="Console / Output", lines=21, interactive=False, show_copy_button=True, max_lines=50)
|
| 118 |
+
|
| 119 |
+
execute_btn.click(
|
| 120 |
+
fn=intelligent_agent_ide,
|
| 121 |
+
inputs=[code_editor, instruction_box],
|
| 122 |
+
outputs=[code_editor, output_box]
|
| 123 |
+
)
|
| 124 |
+
|
| 125 |
+
with gr.TabItem("🛠️ MCP Tools API"):
|
| 126 |
+
gr.Markdown("## Available MCP Tools for other Agents\nThese APIs are the building blocks of our IDE agent.")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 127 |
with gr.Accordion("Tool: Generate C Code", open=False):
|
| 128 |
+
# MCP용 툴은 'generate_c_code' 함수를 직접 노출
|
| 129 |
+
prompt_input = gr.Textbox(label="Description")
|
| 130 |
+
code_output = gr.Code(language="c", label="Generated C Code")
|
| 131 |
+
gr.Interface(fn=generate_c_code, inputs=prompt_input, outputs=code_output)
|
| 132 |
with gr.Accordion("Tool: Compile & Run C Code", open=False):
|
| 133 |
+
code_input_run = gr.Code(language="c", label="C Code to Run")
|
| 134 |
+
text_output_run = gr.Textbox(label="Output")
|
| 135 |
+
gr.Interface(fn=compile_and_run_c_code, inputs=code_input_run, outputs=text_output_run)
|
| 136 |
|
| 137 |
if __name__ == "__main__":
|
| 138 |
demo.queue().launch()
|