Spaces:
Running
Running
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()
|